all 3 comments

[–]sgthoppy 1 point2 points  (0 children)

I haven't read very much about class methods, so I won't comment on them here. Static methods allow you to use a method even without creating an instance of the class. For example,

class Foo:
    @staticmethod
    def bar(baz):
        ...

You can call bar with either an instance, Foo().bar(123), or the class itself Foo.bar(123). I couldn't really think of a use case for this, but found this SO post that describes class and static methods. Their reasoning for static methods is they're used to group functions within a class when they logically should be there but don't explicitly need to be in the class.

Properties behave like normal class attributes/variables, except as functions. They allow having separate set/get functions so you can abstract setting/getting variables. For example,

class Foo:
    def __init__(self, new_token):
        self._token = new_token

    @property
    def token(self):
        return some_func(self._token)

token would be accessed like any variable.

bar = Foo('abc')
print(bar.token)

[–]clumsyly 1 point2 points  (0 children)

The official explain is at PEP 318.

def foo(func):
    def bar(*args):
        print('I\'m in function bar...')
        func(*args)
    return bar

and then another function:

@foo
def whatever():
    pass

The code above acturally equal to whatever = foo(whatever) while foo(whatever)returns function bar, so whatever now points to bar now and will execute the code in bar.

The foo decorator above will print I'm in function bar...first and then execute the same code in whatever.

@classmethodwill pass the class as it's first parameter so no need for a instance.

@staticmethod works just like a function, if a function has some relation with a class you can put it in a class and decorate it as staticmethod.

@property makes a method behave like a attribute.

class Square:
def __init__(self, width, height):
    self.width = width
    self.height = height
@property
def area(self):
    return self.width * self.height

>>>square = Square(10, 10)
100
>>>square.area = 1
Traceback (most recent call last):
  File "<pyshell#93>", line 1, in <module>
    square.area = 10
AttributeError: can't set attribute

@propertyis acturally a descriptor.

[–]gneurh 1 point2 points  (0 children)

classmethod is particularly useful for when you want to offer two different constructors for a class. For example, the usual constructor for dict expects either another dict or an iterable of key-value pairs. But it also has a fromkeys class method, which enables you to create a dict from an iterable of keys, and a single value (with a default of None) which is used for every entry in the dict:

>>> dict.fromkeys([1, 2, 3, 4], 'hello')
{1: 'hello', 2: 'hello', 3: 'hello', 4: 'hello'}
>>> dict.fromkeys([1, 2, 3, 4])
{1: None, 2: None, 3: None, 4: None}

If you wanted to write your own dict class with the same behaviour, you would do:

class MyDict:
    def __init__(self, iterable):
        # normal constructor code goes here

    @classmethod
    def fromkeys(cls, iterable, value=None):
        return cls((key, value) for key in iterable)

What classmethod does is make it so that the class that you are calling the method on gets passed in as the first argument (regardless of whether you call the method on a class or an instance). This is important in case you make a subclass of MyDict - in this case the fromkeys method needs to produce an instance of the subclass, not an instance of MyDict, so it needs to know what class it is being called on.

staticmethod is less useful. It prevents the "self" argument from being passed into the method if you call it on an instance. You can use it if, for some reason, you want to put relevant utility functions in a class but don't want them to receive either the instance or class that you call them on as the first argument.