Solved

learning python, have some concept questions

Posted on 2012-03-21
18
362 Views
Last Modified: 2012-03-28
I am currently learning Python for a new job.  I've been reading through the docs at python.org, and most seems pretty straight-forward.  I have run into a few oddities, though:

1) Using the specific example at http://docs.python.org/library/functions.html#print, I issued the command "from __future__ import print_function".  That all worked as advertised.  Now I want to revert to the original print() built-in.  I tried "del print_function", and it was successfully removed from the globals()/dir() return, but the functionality is still there.  See below for the code sample.
$> python
Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> a=20
>>> b=30
>>> print a,b
20 30
>>> print (a,b,sep='')
  File "<stdin>", line 1
    print (a,b,sep='')
                  ^
SyntaxError: invalid syntax
>>> from __future__ import print_function
>>> print (a,b,sep='')
2030
>>> del print_function
>>> print (a,b,sep='')
2030
>>>

Open in new window


2) If all class/object methods implicitly default to expecting a self-reference as the first parameter, is there any additional purpose/functionality associated with the @classmethod decorator?
0
Comment
Question by:Steve Bink
  • 7
  • 6
  • 5
18 Comments
 
LVL 41

Assisted Solution

by:HonorGod
HonorGod earned 200 total points
ID: 37749040
1. I don't believe that a revert or undo mechanism exists for this kind of thing.
2. I know of none, but others (e.g., @pepr) may.  ;-)
0
 
LVL 28

Expert Comment

by:pepr
ID: 37749892
As far as I know, the "from __future__ ..." is a bit unusual command.  It sets some flags in the interpreter to unblock the implemented but otherwise blocked functionality.  I have never searched if it can be reverted.  Simply, run the interpreter again, and do not use the "from __future__ ....".
0
 
LVL 50

Author Comment

by:Steve Bink
ID: 37750178
@pepr: That is how I resolved it on this occasion.  Since I'm a bit new to this, I was wondering if there was another way to revert it.  It was just something I stumbled across while playing around.

Any ideas on the second item?
0
 
LVL 41

Assisted Solution

by:HonorGod
HonorGod earned 200 total points
ID: 37750182
I agree, once the interpreter flag is set, there doesn't appear to be a way to unset it.

Python 2.7.2 (default, Jun 24 2011, 12:22:14) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> print 'hi'
hi
>>> from __future__ import print_function
>>> print( 'hi' )
hi
>>> locals()[ 'print_function' ]
_Feature((2, 6, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 65536)
>>> del locals()[ 'print_function' ]
>>> locals()[ 'print_function' ]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'print_function'
>>> print( 'hi' )
hi
>>>

Open in new window

0
 
LVL 28

Assisted Solution

by:pepr
pepr earned 300 total points
ID: 37761332
@routinet:  Actually, you can look inside the python26/Lib/__future__.py.  You can find the explanation of the mechanism there.  It says:

CompilerFlag is the (bitfield) flag that should be passed in the fourth
argument to the builtin function compile() to enable the feature in
dynamically compiled code.

In other words, the flag is passed to the compiler, and it generates a different code after that.  The only way would be to recompile the dynamically compiled code again.  I have never tried.  It possibly can be done, but I can see no reason for doing that (as the beginner).

The mechanism is here to use some future features if it makes sense for your project.  If you are only learning the things, more convenient way could be to install both the Python 2.x and 3.x side-by-side.

I suggest to have a look at "Dive Into Python 3" by Mark Pilgrim (http://diveintopython3.ep.io/index.html).  The "Appendix A. Porting Code to Python 3 with 2to3" (http://diveintopython3.ep.io/porting-code-to-python-3-with-2to3.html) may help you to decide what features you should get used to and why.

Many of the new features of 3.x are implemented in 2.7.  If you can choose, use the 2.7 if you want to use the version 2.x.
0
 
LVL 50

Author Comment

by:Steve Bink
ID: 37762141
Well, I am learning, but the environment I'm learning for is Python 2.6.  At the moment, that cannot be changed... I'll have to tackle Python 3 once I have a spare month or two.  :)

What you say as far as the compiling makes sense.  If there is no way to reverse, then it is what it is.  The code base is not using any __future__ features that I know of, so this is really for my own curiosity and knowledge of the language.  

Regarding the second part, I've found no advantage or disadvantage to specifying @classmethod.  Do you know of any, or is this just a redundant concept?
0
 
LVL 41

Expert Comment

by:HonorGod
ID: 37762685
From the documentation, specifically:
http://docs.python.org/glossary.html#term-decorator

The decorator syntax is merely syntactic sugar, the following two function definitions are semantically equivalent:

def f(...):
    ...
f = staticmethod(f)

@staticmethod
def f(...):
    ...

Open in new window

0
 
LVL 50

Author Comment

by:Steve Bink
ID: 37762775
I understand about @staticmethod. I also see the point to it - a static method will act on an object's definition, not on an instance.  By default, every method is understood to be a class method, in that it implicitly receives a first parameter of self, the instance on which it must act.  Using @staticmethod will change that behavior.  What does @classmethod do?
0
 
LVL 41

Expert Comment

by:HonorGod
ID: 37765201
The difference between static and class methods is that class methods include / require a "self" parameter that is used to identify the object instance being referenced.
0
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
LVL 50

Author Comment

by:Steve Bink
ID: 37766914
I understand the difference between a static method and a class method.  My question is how a general class method definition differs from a class method definition using @classmethod.
0
 
LVL 41

Expert Comment

by:HonorGod
ID: 37773344
I'm not 100% certain, but I think that the @classmethod decorator would be used only within a class, and identifies the need for the instance reference (self) to be provided when the method is invoked (called)
0
 
LVL 50

Author Comment

by:Steve Bink
ID: 37774384
I agree, but if @classmethod is not present, that is also the default behavior.  I'm asking if there is any difference between the default behavior and the @classmethod behavior.
0
 
LVL 28

Accepted Solution

by:
pepr earned 300 total points
ID: 37775272
> My question is how a general class method definition differs
> from a class method definition using @classmethod.


The most usual thing is not to use either @staticmethod nor @classmethod.  You do not need them until you really understand using the normal classes and their instances.

A usual method of a class is defined with the self argument at the first place. You can think about it as about a normal function that gets its arguments. When a normal method is called, the instance of the class (the object)--or better to say the reference to the object--is passed to the function.  The only difference from a normal function is that the first argument is not passed as the first one from inside the parenthesis; instead, the first argument is considered the one that was typed-in before the dot in front of the method name.  Actually, this is a trick in any object oriented language.  It helps our imagination to think about the object as about the self-standing entity, and as about using its own ability to do something.  Inside the function body, the reference to the object is passed and it was named self.  

A static method (@staticmethod) does not get the self argument.  It is usually called for the class name in front of the dot.  That kind of function is closer to "normal" functions.

A @classmethod function gets the cls as the first argument (the name of the argument by convention, similarly to self).  This means that it does not get the reference to the object, but to its class.  It does not matter whether you call it for a class or for an object.  You always get the reference to the class as the first argument of the function.  It also means that the function does not have the access to the object data members if it was called via the object -- because there is no self.

To summarize: a usual method gets self, a @classmethod gets cls, and a @staticmethod gets nothing related to the class nor to the object (only the other passed arguments).

It can be useful for you to think about what the doc says http://docs.python.org/reference/datamodel.html#the-standard-type-hierarchy -- a bit below.  Focus on the term, that the decorators make a wrapper around the decorated thing (here the method):

Static method objects
    Static method objects provide a way of defeating the transformation of function objects to method objects described above. A static method object is a wrapper around any other object, usually a user-defined method object. When a static method object is retrieved from a class or a class instance, the object actually returned is the wrapped object, which is not subject to any further transformation. Static method objects are not themselves callable, although the objects they wrap usually are. Static method objects are created by the built-in staticmethod() constructor.

Class method objects
    A class method object, like a static method object, is a wrapper around another object that alters the way in which that object is retrieved from classes and class instances. The behaviour of class method objects upon such retrieval is described above, under “User-defined methods”. Class method objects are created by the built-in classmethod() constructor.
0
 
LVL 50

Author Comment

by:Steve Bink
ID: 37775481
I see the difference now, but I'm not sure I understand it.  When I read through that material previously, I assumed the "cls" reference was the same as a "self" reference.  That gave me the impression that these two definitions were functionally equivalent:

class MyClass:
    def func_one(self):
        pass

    @classmethod
    def func_two(cls):
        pass

Open in new window


Assuming the definition above, func_one() is a "standard" method, which, when called, will implicitly receive the self object inserted as the first parameter.  The call would actually appear as "func_one()".  Inside the execution of func_one(), I would have access to any other properties/methods/members associated with that particular instance of MyClass (i.e., the object).  

What is exposed to func_two()?  I understand (finally) that the implicit first parameter will be the class definition, not the object itself.  Python allows for class-level variables (the same concept as "static" class properties in PHP, as I understand it), so I imagine those will be available as cls.prop_a, and so on.  Is there any other reason to use a @classmethod decorator?  Does that mean the two method definitions in the code sample below are functionally equivalent?

class MyClass:
    prop_a = 1
    
    @staticmethod
    def func_one():
        print MyClass.prop_a
 
    @classmethod
    def func_two(cls):
        print cls.prop_a

Open in new window


In other words, I guess my question has now changed to the behavioral differences between the @classmethod and @staticmethod decorators.  Besides the calling and reference semantics (i.e., the implicit parameter), are there any reasons to use one decorator over another?
0
 
LVL 28

Assisted Solution

by:pepr
pepr earned 300 total points
ID: 37776159
You rarely need the @staticmethod.  Using the @classmethod is even rarer.  You should possibly ask for "good real example that justifies usage of @classmethod".

In my opinion, the @classmethod makes sense only in superclass that is inherited by other classes, for example for some introspection code that gets some information from the derived class.  What I mean is that you have an object my_obj of SomeClass that is derived from your base class MyClass.  Then you occasionally call:

my_obj.func_two()

The func_two() gets the cls that refers to the derived class even though the function is defined in the base class.  You can call func_two() as SomeClass.func_two(), but in the case you know the SameClass.  In the my_obj case, you may not know the class, even though it is not difficult to get the reference to the class as my_obj.__class__

@classmethod does not have access to the object, only to the class.

@staticmethod does not have access the object, and it does not have access to the class either (even though it can be called via the object or via the class).

Other things to think about -- try the following simple example:

def func_three():
    print 'three', MyClass.prop_a


class MyClass:
    prop_a = 1

    def func_zero(self):
        print 'zero ', self.prop_a

    @staticmethod
    def func_one():
        print 'one  ', MyClass.prop_a

    @classmethod
    def func_two(cls):
        print 'two  ', cls.prop_a


obj = MyClass()
obj.func_zero()
obj.func_one()
obj.func_two()
func_three()

Open in new window


It prints on my console:

c:\tmp\___python\routinet\Q_27642767>python a.py
zero  1
one   1
two   1
three 1

Open in new window

0
 
LVL 28

Expert Comment

by:pepr
ID: 37776174
Now try the enhanced example:

b.py
def func_three():
    print 'three', MyClass.prop_a


class MyClass:
    prop_a = 1

    def func_zero(self):
        print 'zero ', self.prop_a

    @staticmethod
    def func_one():
        print 'one  ', MyClass.prop_a

    @classmethod
    def func_two(cls):
        print 'two  ', cls.prop_a


class MyDerivedClass(MyClass):
    prop_a = 2
    

obj = MyDerivedClass()
obj.func_zero()
obj.func_one()
obj.func_two()
func_three()

Open in new window


Notice that the object is of the derived class that only differs in the prop_a value.  It prints on my console:

c:\tmp\___python\routinet\Q_27642767>python b.py
zero  2
one   1
two   2
three 1

Open in new window

0
 
LVL 50

Author Comment

by:Steve Bink
ID: 37778398
I think you're right about the question...I should be asking for an example of justified usage.

In any case, I understand it now.  Thanks much for your explanation.
0
 
LVL 41

Expert Comment

by:HonorGod
ID: 37778621
Thanks for the assist, the points, and the interesting questions.

Good luck & have a great day.
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Plenty of writing has gone on the web trying to compare Python with other competitive programming languages and vice versa. However, not much has been put into a wholistic perspective. This article should help you decide whether to adopt Python as a…
The really strange introduction Once upon a time there were individuals who intentionally put the grass seeds to the soil with anticipation of solving their nutrition problems. Or they maybe only played with seeds and noticed what happened... Som…
Learn the basics of strings in Python: declaration, operations, indices, and slicing. Strings are declared with quotations; for example: s = "string": Strings are immutable.: Strings may be concatenated or multiplied using the addition and multiplic…
Learn the basics of lists in Python. Lists, as their name suggests, are a means for ordering and storing values. : Lists are declared using brackets; for example: t = [1, 2, 3]: Lists may contain a mix of data types; for example: t = ['string', 1, T…

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now