Python - How use properties without creating an object - python

How do I write a class to make this code work.
class number:
def double(self):
return n*2
print(number(44).double)
>> 88

Well, you could decorate the number.double method with property:
class number:
def __init__(self, number):
self.number = number
#property
def double(self):
return self.number * 2
print(number(42).double) # 84
If you know the type of your argument, it'd be better to inherit number from it. For example
class number(int):
#property
def double(self):
return type(self)(self * 2)
print(number(42).double) # 84
print(number(42).double.double) # 168

Here you are:
class Number(object):
def __init__(self, n):
self.n = n
def double(self):
return 2*self.n
print(Number(44).double())
A couple of notes:
Since double() is a method of the class Number (and not an attribute), you need to use parentheses to call it.
In Python it's considered standard practice to give classes uppercase names.
If you want to define an instance variable (in this case n, or 44, you must def the __init__() function which gives the interpreter instructions for how to create, or initialize an instance of your class.
Hope this helps, and good luck!

Related

What's the best way to define a function (not a method) inside a class? [duplicate]

Can I define a static method which I can call directly on the class instance? e.g.,
MyClass.the_static_method()
Yep, using the staticmethod decorator:
class MyClass(object):
#staticmethod
def the_static_method(x):
print(x)
MyClass.the_static_method(2) # outputs 2
Note that some code might use the old method of defining a static method, using staticmethod as a function rather than a decorator. This should only be used if you have to support ancient versions of Python (2.2 and 2.3):
class MyClass(object):
def the_static_method(x):
print(x)
the_static_method = staticmethod(the_static_method)
MyClass.the_static_method(2) # outputs 2
This is entirely identical to the first example (using #staticmethod), just not using the nice decorator syntax.
Finally, use staticmethod sparingly! There are very few situations where static-methods are necessary in Python, and I've seen them used many times where a separate "top-level" function would have been clearer.
The following is verbatim from the documentation::
A static method does not receive an implicit first argument. To declare a static method, use this idiom:
class C:
#staticmethod
def f(arg1, arg2, ...): ...
The #staticmethod form is a function decorator – see the description of function definitions in Function definitions for details.
It can be called either on the class (such as C.f()) or on an instance (such as C().f()). The instance is ignored except for its class.
Static methods in Python are similar to those found in Java or C++. For a more advanced concept, see classmethod().
For more information on static methods, consult the documentation on the standard type hierarchy in The standard type hierarchy.
New in version 2.2.
Changed in version 2.4: Function decorator syntax added.
I think that Steven is actually right. To answer the original question, then, in order to set up a class method, simply assume that the first argument is not going to be a calling instance, and then make sure that you only call the method from the class.
(Note that this answer refers to Python 3.x. In Python 2.x you'll get a TypeError for calling the method on the class itself.)
For example:
class Dog:
count = 0 # this is a class variable
dogs = [] # this is a class variable
def __init__(self, name):
self.name = name #self.name is an instance variable
Dog.count += 1
Dog.dogs.append(name)
def bark(self, n): # this is an instance method
print("{} says: {}".format(self.name, "woof! " * n))
def rollCall(n): #this is implicitly a class method (see comments below)
print("There are {} dogs.".format(Dog.count))
if n >= len(Dog.dogs) or n < 0:
print("They are:")
for dog in Dog.dogs:
print(" {}".format(dog))
else:
print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))
fido = Dog("Fido")
fido.bark(3)
Dog.rollCall(-1)
rex = Dog("Rex")
Dog.rollCall(0)
In this code, the "rollCall" method assumes that the first argument is not an instance (as it would be if it were called by an instance instead of a class). As long as "rollCall" is called from the class rather than an instance, the code will work fine. If we try to call "rollCall" from an instance, e.g.:
rex.rollCall(-1)
however, it would cause an exception to be raised because it would send two arguments: itself and -1, and "rollCall" is only defined to accept one argument.
Incidentally, rex.rollCall() would send the correct number of arguments, but would also cause an exception to be raised because now n would be representing a Dog instance (i.e., rex) when the function expects n to be numerical.
This is where the decoration comes in:
If we precede the "rollCall" method with
#staticmethod
then, by explicitly stating that the method is static, we can even call it from an instance. Now,
rex.rollCall(-1)
would work. The insertion of #staticmethod before a method definition, then, stops an instance from sending itself as an argument.
You can verify this by trying the following code with and without the #staticmethod line commented out.
class Dog:
count = 0 # this is a class variable
dogs = [] # this is a class variable
def __init__(self, name):
self.name = name #self.name is an instance variable
Dog.count += 1
Dog.dogs.append(name)
def bark(self, n): # this is an instance method
print("{} says: {}".format(self.name, "woof! " * n))
#staticmethod
def rollCall(n):
print("There are {} dogs.".format(Dog.count))
if n >= len(Dog.dogs) or n < 0:
print("They are:")
for dog in Dog.dogs:
print(" {}".format(dog))
else:
print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))
fido = Dog("Fido")
fido.bark(3)
Dog.rollCall(-1)
rex = Dog("Rex")
Dog.rollCall(0)
rex.rollCall(-1)
Yes, check out the staticmethod decorator:
>>> class C:
... #staticmethod
... def hello():
... print "Hello World"
...
>>> C.hello()
Hello World
You don't really need to use the #staticmethod decorator. Just declaring a method (that doesn't expect the self parameter) and call it from the class. The decorator is only there in case you want to be able to call it from an instance as well (which was not what you wanted to do)
Mostly, you just use functions though...
Static methods in Python?
Is it possible to have static methods in Python so I can call them
without initializing a class, like:
ClassName.StaticMethod()
Yes, static methods can be created like this (although it's a bit more Pythonic to use underscores instead of CamelCase for methods):
class ClassName(object):
#staticmethod
def static_method(kwarg1=None):
'''return a value that is a function of kwarg1'''
The above uses the decorator syntax. This syntax is equivalent to
class ClassName(object):
def static_method(kwarg1=None):
'''return a value that is a function of kwarg1'''
static_method = staticmethod(static_method)
This can be used just as you described:
ClassName.static_method()
A builtin example of a static method is str.maketrans() in Python 3, which was a function in the string module in Python 2.
Another option that can be used as you describe is the classmethod, the difference is that the classmethod gets the class as an implicit first argument, and if subclassed, then it gets the subclass as the implicit first argument.
class ClassName(object):
#classmethod
def class_method(cls, kwarg1=None):
'''return a value that is a function of the class and kwarg1'''
Note that cls is not a required name for the first argument, but most experienced Python coders will consider it badly done if you use anything else.
These are typically used as alternative constructors.
new_instance = ClassName.class_method()
A builtin example is dict.fromkeys():
new_dict = dict.fromkeys(['key1', 'key2'])
Perhaps the simplest option is just to put those functions outside of the class:
class Dog(object):
def __init__(self, name):
self.name = name
def bark(self):
if self.name == "Doggy":
return barking_sound()
else:
return "yip yip"
def barking_sound():
return "woof woof"
Using this method, functions which modify or use internal object state (have side effects) can be kept in the class, and the reusable utility functions can be moved outside.
Let's say this file is called dogs.py. To use these, you'd call dogs.barking_sound() instead of dogs.Dog.barking_sound.
If you really need a static method to be part of the class, you can use the staticmethod decorator.
Aside from the particularities of how static method objects behave, there is a certain kind of beauty you can strike with them when it comes to organizing your module-level code.
# garden.py
def trim(a):
pass
def strip(a):
pass
def bunch(a, b):
pass
def _foo(foo):
pass
class powertools(object):
"""
Provides much regarded gardening power tools.
"""
#staticmethod
def answer_to_the_ultimate_question_of_life_the_universe_and_everything():
return 42
#staticmethod
def random():
return 13
#staticmethod
def promise():
return True
def _bar(baz, quux):
pass
class _Dice(object):
pass
class _6d(_Dice):
pass
class _12d(_Dice):
pass
class _Smarter:
pass
class _MagicalPonies:
pass
class _Samurai:
pass
class Foo(_6d, _Samurai):
pass
class Bar(_12d, _Smarter, _MagicalPonies):
pass
...
# tests.py
import unittest
import garden
class GardenTests(unittest.TestCase):
pass
class PowertoolsTests(unittest.TestCase):
pass
class FooTests(unittest.TestCase):
pass
class BarTests(unittest.TestCase):
pass
...
# interactive.py
from garden import trim, bunch, Foo
f = trim(Foo())
bunch(f, Foo())
...
# my_garden.py
import garden
from garden import powertools
class _Cowboy(garden._Samurai):
def hit():
return powertools.promise() and powertools.random() or 0
class Foo(_Cowboy, garden.Foo):
pass
It now becomes a bit more intuitive and self-documenting in which context certain components are meant to be used and it pans out ideally for naming distinct test cases as well as having a straightforward approach to how test modules map to actual modules under tests for purists.
I frequently find it viable to apply this approach to organizing a project's utility code. Quite often, people immediately rush and create a utils package and end up with 9 modules of which one has 120 LOC and the rest are two dozen LOC at best. I prefer to start with this and convert it to a package and create modules only for the beasts that truly deserve them:
# utils.py
class socket(object):
#staticmethod
def check_if_port_available(port):
pass
#staticmethod
def get_free_port(port)
pass
class image(object):
#staticmethod
def to_rgb(image):
pass
#staticmethod
def to_cmyk(image):
pass
So, static methods are the methods which can be called without creating the object of a class.
For Example :-
#staticmethod
def add(a, b):
return a + b
b = A.add(12,12)
print b
In the above example method add is called by the class name A not the object name.
Summarizing others' answers and adding, there are many ways to declare Static Methods or Variables in python.
Using staticmethod() as a decorator:
One can simply put a decorator above a method(function) declared to make it a static method. For eg.
class Calculator:
#staticmethod
def multiply(n1, n2, *args):
Res = 1
for num in args: Res *= num
return n1 * n2 * Res
print(Calculator.multiply(1, 2, 3, 4)) # 24
Using staticmethod() as a parameter function:
This method can receive an argument which is of function type, and it returns a static version of the function passed. For eg.
class Calculator:
def add(n1, n2, *args):
return n1 + n2 + sum(args)
Calculator.add = staticmethod(Calculator.add)
print(Calculator.add(1, 2, 3, 4)) # 10
Using classmethod() as a decorator:
#classmethod has similar effect on a function as #staticmethod has, but
this time, an additional argument is needed to be accepted in the function (similar to self parameter for instance variables). For eg.
class Calculator:
num = 0
def __init__(self, digits) -> None:
Calculator.num = int(''.join(digits))
#classmethod
def get_digits(cls, num):
digits = list(str(num))
calc = cls(digits)
return calc.num
print(Calculator.get_digits(314159)) # 314159
Using classmethod() as a parameter function:
#classmethod can also be used as a parameter function, in case one doesn't want to modify class definition. For eg.
class Calculator:
def divide(cls, n1, n2, *args):
Res = 1
for num in args: Res *= num
return n1 / n2 / Res
Calculator.divide = classmethod(Calculator.divide)
print(Calculator.divide(15, 3, 5)) # 1.0
Direct declaration
A method/variable declared outside all other methods, but inside a class is automatically static.
class Calculator:
def subtract(n1, n2, *args):
return n1 - n2 - sum(args)
print(Calculator.subtract(10, 2, 3, 4)) # 1
The whole program
class Calculator:
num = 0
def __init__(self, digits) -> None:
Calculator.num = int(''.join(digits))
#staticmethod
def multiply(n1, n2, *args):
Res = 1
for num in args: Res *= num
return n1 * n2 * Res
def add(n1, n2, *args):
return n1 + n2 + sum(args)
#classmethod
def get_digits(cls, num):
digits = list(str(num))
calc = cls(digits)
return calc.num
def divide(cls, n1, n2, *args):
Res = 1
for num in args: Res *= num
return n1 / n2 / Res
def subtract(n1, n2, *args):
return n1 - n2 - sum(args)
Calculator.add = staticmethod(Calculator.add)
Calculator.divide = classmethod(Calculator.divide)
print(Calculator.multiply(1, 2, 3, 4)) # 24
print(Calculator.add(1, 2, 3, 4)) # 10
print(Calculator.get_digits(314159)) # 314159
print(Calculator.divide(15, 3, 5)) # 1.0
print(Calculator.subtract(10, 2, 3, 4)) # 1
Refer to Python Documentation for mastering OOP in python.
Python Static methods can be created in two ways.
Using staticmethod()
class Arithmetic:
def add(x, y):
return x + y
# create add static method
Arithmetic.add = staticmethod(Arithmetic.add)
print('Result:', Arithmetic.add(15, 10))
Output:
Result: 25
Using #staticmethod
class Arithmetic:
# create add static method
#staticmethod
def add(x, y):
return x + y
print('Result:', Arithmetic.add(15, 10))
Output:
Result: 25
You can use #staticmethod decorator to define a static method as shown below. In detail, I explain about #staticmethod decorator and #classmethod decorator in my answer for #classmethod vs #staticmethod in Python and also explain about instance method in my answer for What is an "instance method" in Python?:
class Person:
#staticmethod # Here
def test():
print("Test")
I encounter this question from time to time. The use case and example that I am fond of is:
jeffs#jeffs-desktop:/home/jeffs $ python36
Python 3.6.1 (default, Sep 7 2017, 16:36:03)
[GCC 6.3.0 20170406] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cmath
>>> print(cmath.sqrt(-4))
2j
>>>
>>> dir(cmath)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 'cos', 'cosh', 'e', 'exp', 'inf', 'infj', 'isclose', 'isfinite', 'isinf', 'isnan', 'log', 'log10', 'nan', 'nanj', 'phase', 'pi', 'polar', 'rect', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau']
>>>
It does not make sense to create an object of class cmath, because there is no state in a cmath object. However, cmath is a collection of methods that are all related in some way. In my example above, all of the functions in cmath act on complex numbers in some way.

How to make instance specific methods in python

So I've come across this problem, it's kind of hard to explain so i'll try with a pizza analogy:
We have the following classes:
class Storage:
# this seems like i should use a dict, but let's assume there is more functionality to it
def __init__(self, **kwargs):
self.storage = kwargs
# use like: Storage(tomato_cans=50, mozzarella_slices=200, ready_dough=20)
def new_item(self, item_name: str, number: int):
self.storage[item_name] = number
def use(self, item_name: str, number: int):
self.storage[item_name] = self.storage.get(item_name) - number
def buy(self, item_name: str, number: int):
self.storage[item_name] = self.storage.get(item_name) + number
class Oven:
def __init__(self, number_parallel):
# number of parallel pizzas possible
self.timers = [0] * number_parallel
def ready(self):
return 0 in self.timers
def use(for_mins):
for i, timer in enumerate(self.timers):
if timer == 0:
self.timers[i] = for_mins
break
def pass_time(mins):
for i in range(len(self.timers)):
self.timers[i] = max(0, self.timers[i]-mins)
class Pizza:
def __init__(self, minutes=6, dough=1, tomato_cans=1, mozzarella_slices=8, **kwargs):
self.ingredients = kwargs
self.ingredients['dough'] = dough
self.ingredients['tomato_cans'] = tomato_cans
self.ingredients['mozzarella_slices'] = mozzarella_slices
self.minutes = minutes
def possible(self, oven, storage):
if not oven.ready():
return False
for key, number in self.ingredients:
if number > storage.storage.get(key, 0):
return False
return True
def put_in_oven(self, oven, storage):
oven.use(self.minutes)
for key, number in self.ingredients:
storage.use(key, number)
We can make Pizzas now, e.g.:
storage = Storage()
oven = Oven(2)
margherita = Pizza()
prosciutto = Pizza(ham_slices=7)
if margherita.possible():
margherita.put_in_oven()
storage.new_item('ham_slices', 20)
if prosciutto.possible():
prosciutto.put_in_oven()
And now my question (sorry if this was too detailed):
Can I create a Pizza instance and change it's put_in_oven method?
Like for example a Pizza where you'd have to cook some vegetables first or check if it's the right season in the possible method.
I imagine something like:
vegetariana = Pizza(paprika=1, arugula=5) # something like that i'm not a pizzaiolo
def vegetariana.put_in_oven(self, oven, storage):
cook_vegetables()
super().put_in_oven() # call Pizza.put_in_oven
I hope this question is not too cumbersome!
Edit:
So let's suppose we would use inheritance:
class VeggiePizza(Pizza):
def put_in_oven(self, oven, storage):
self.cut_veggies()
super().put_in_oven(oven, storage)
def cut_veggies(self):
# serves purpose of explaining
# analogy has its limits
pass
class SeasonalPizza(Pizza):
def __init__(self, season_months, minutes=6, dough=1, tomato_cans=1, mozzarella_slices=8, **kwargs):
self.season_months # list of month integers (1 - 12)
super().__init__()
def possible(self, oven, storage):
return super().possible(oven, storage) and datetime.datetime.now().month in self.season_months
My Problem with that is, because I might make a Seasonal Veggie Pizza or other Subclasses or again different combinations of them or even Subclasses which may serve only one instance.
E.g. For a PizzaAmericano (has French Fries on top), I'd use a Subclass like VeggiePizza and put fry_french_fries() in front of super().put_in_oven() and I'd definitely not use that Subclass for any other instance than the pizza_americano (unlike the VeggiePizza, where you can make different vegetarian pizze).
Is that ok? For me it seems to contradict to the principle of classes.
EDIT:
Okay, thanks to your answers and this recommended question I now know how to add/change a method of an instance. But before I close this question as a duplicate; Is that generally something that's totally fine or rather advised against? I mean it seems pretty unnatural for the simplicity of it's nature, having an instance specific method, just like instance specific variables.
You can define per instance "methods" indeed (nb: py3 example) - python's "methods" are basically just functions - the only trick is to make sure the function has access to the current instance. Two possible solutions here: use a closure, or explicitely invoke the descriptor protocol on the function.
1/ : with a closure
class Foo:
def __init__(self, x):
self.x = x
def foo(self, bar):
return bar * self.x
def somefunc():
f = Foo(42)
def myfoo(bar):
# myfoo will keep a reference to `f`
return bar * (f.x % 2)
f.foo = myfoo
return f
2/ with the descriptor protocol
# same definition of class Foo
def somefunc()
f = Foo()
def myfoo(self, bar):
return bar * (self.x % 2)
# cf the link above
f.foo = myfoo.__get__(f, type(f))
return f
but the more general solution to your issue are the strategy pattern and possibly the state pattern for the case of SeasonalPizza.possible()
Since your example is a toy exemple I won't bother giving an example with those solution, but they are very straightforward to implement in Python.
Also note that since the goal is mainly to encapsulate those details so the client code doesn't have to bother about which kind of pizza it's dealing with, you'll need some [creational pattern] to deal with this. Note that python classes are already factories, due to the two-stages instanciation process - the constructor __new__() creates an empty uninitialized instance, which is then passed to the initializer __init__(). This means that you can override __new__() to return whatever you want... And since Python's classes are objects themselves, you can extend this further by using a custom metaclass
As a last note: just make sure you keep compatible signatures and return types for all your methods, else you'll break the Liskov subsitution principle and loose the first and main benefit of OO which is to replace conditionals by polymorphic dispatch (IOW: if you break LSP, your client code can no more handle all pizzas type uniformly and ends up full of typechecks and conditionals, which is exactly what OO tries to avoid).
2 possibilities:
either create a case like structure using dicts:
def put_in_oven1(self, *args):
# implementation 1
print('method 1')
def put_in_oven2(self, *args):
# implementation 2
print('method 2')
class pizza:
def __init__(self, method, *args):
self.method = method
pass
def put_in_oven(self, *args):
handles = {
1: put_in_oven1,
2: put_in_oven2}
handles[self.method](self, *args)
my_pizza1 = pizza(1) # uses put_in_oven1
my_pizza1.put_in_oven()
my_pizza2 = pizza(2) # uses put_in_oven2
my_pizza1.put_in_oven()
my_pizza2.put_in_oven()
Or you can change methods dynamically with the setattr
so for example:
from functools import partial
def put_in_oven1(self, *args):
# implementation 1
print('method 1')
def put_in_oven2(self, *args):
# implementation 2
print('method 2')
class pizza:
def __init__(self, *args, **kwargs):
# init
pass
def put_in_oven(self, *args):
# default method
print('default')
pizza1 = pizza()
setattr(pizza1, 'put_in_oven', partial(put_in_oven, self=pizza1))
pizza2 = pizza()
setattr(pizza2, 'put_in_oven', partial(put_in_oven, self=pizza2))
pizza1.put_in_oven()
pizza2.put_in_oven()
or without using partial and defining the methods inside the pizza class
#!/usr/bin/env python
# -*- coding: utf-8 -*-
class pizza:
def put_in_oven1(self, *args):
# implementation 1
print('method 1')
def put_in_oven2(self, *args):
# implementation 2
print('method 2')
def __init__(self, *args, **kwargs):
pass
def put_in_oven(self, *args):
# default
print('default')
pizza1 = pizza()
setattr(pizza1, 'put_in_oven', pizza1.put_in_oven1)
pizza1.put_in_oven()
pizza2 = pizza()
setattr(pizza2, 'put_in_oven', pizza2.put_in_oven2)
pizza2.put_in_oven()

Python generics: how to create object of an appropriate class?

I have the following code (this code is just for testing):
from typing import TypeVar, Generic, Type
import abc
class BaseMultiplier(abc.ABC):
#abc.abstractmethod
def multiply(self, n):
pass
class MultiplierByTwo(BaseMultiplier):
def multiply(self, n):
return n * 2
class MultiplierByThree(BaseMultiplier):
def multiply(self, n):
return n * 3
Multiplier = TypeVar('Multiplier', Type[MultiplierByTwo], Type[MultiplierByThree])
class MultiplierCreator(Generic[Multiplier]):
def create(self) -> Multiplier:
# I need to create an instance of Multiplier here
pass
class MultiplierByTwoCreator(MultiplierCreator[MultiplierByTwo]):
pass
class MultiplierByThreeCreator(MultiplierCreator[MultiplierByThree]):
pass
So how can I create an instance of an appropriate Multiplier class in create method?
So the following code must not raise any exceptions:
creator_by_two = MultiplierByTwoCreator()
assert type(creator_by_two.create()) == MultiplierByTwo
creator_by_three = MultiplierByThreeCreator()
assert type(creator_by_three.create()) == MultiplierByThree
Thanks in advance.
class MultiplierCreator(Generic[Multiplier]):
def create(self) -> Multiplier:
return self.multiplier()
class MultiplierByTwoCreator(MultiplierCreator[MultiplierByTwo]):
multiplier = MultiplierByTwo
class MultiplierByThreeCreator(MultiplierCreator[MultiplierByThree]):
multiplier = MultiplierByThree
By adding class attributes to the subclasses of MultiplierCreator that contain the related Multiplier subclass you can then use the inherited method create() to call this class attributes and return an instance of it. Hope this is what you are looking for.
Aside from that, to check whether an object is of the correct type you may want to use isinstance():
assert isinstance(creator_by_two.create(), MultiplierByTwo)
assert isinstance(creator_by_three.create(), MultiplierByThree)
Hopefully this can help you.

what does it means that method should be static? [duplicate]

Can I define a static method which I can call directly on the class instance? e.g.,
MyClass.the_static_method()
Yep, using the staticmethod decorator:
class MyClass(object):
#staticmethod
def the_static_method(x):
print(x)
MyClass.the_static_method(2) # outputs 2
Note that some code might use the old method of defining a static method, using staticmethod as a function rather than a decorator. This should only be used if you have to support ancient versions of Python (2.2 and 2.3):
class MyClass(object):
def the_static_method(x):
print(x)
the_static_method = staticmethod(the_static_method)
MyClass.the_static_method(2) # outputs 2
This is entirely identical to the first example (using #staticmethod), just not using the nice decorator syntax.
Finally, use staticmethod sparingly! There are very few situations where static-methods are necessary in Python, and I've seen them used many times where a separate "top-level" function would have been clearer.
The following is verbatim from the documentation::
A static method does not receive an implicit first argument. To declare a static method, use this idiom:
class C:
#staticmethod
def f(arg1, arg2, ...): ...
The #staticmethod form is a function decorator – see the description of function definitions in Function definitions for details.
It can be called either on the class (such as C.f()) or on an instance (such as C().f()). The instance is ignored except for its class.
Static methods in Python are similar to those found in Java or C++. For a more advanced concept, see classmethod().
For more information on static methods, consult the documentation on the standard type hierarchy in The standard type hierarchy.
New in version 2.2.
Changed in version 2.4: Function decorator syntax added.
I think that Steven is actually right. To answer the original question, then, in order to set up a class method, simply assume that the first argument is not going to be a calling instance, and then make sure that you only call the method from the class.
(Note that this answer refers to Python 3.x. In Python 2.x you'll get a TypeError for calling the method on the class itself.)
For example:
class Dog:
count = 0 # this is a class variable
dogs = [] # this is a class variable
def __init__(self, name):
self.name = name #self.name is an instance variable
Dog.count += 1
Dog.dogs.append(name)
def bark(self, n): # this is an instance method
print("{} says: {}".format(self.name, "woof! " * n))
def rollCall(n): #this is implicitly a class method (see comments below)
print("There are {} dogs.".format(Dog.count))
if n >= len(Dog.dogs) or n < 0:
print("They are:")
for dog in Dog.dogs:
print(" {}".format(dog))
else:
print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))
fido = Dog("Fido")
fido.bark(3)
Dog.rollCall(-1)
rex = Dog("Rex")
Dog.rollCall(0)
In this code, the "rollCall" method assumes that the first argument is not an instance (as it would be if it were called by an instance instead of a class). As long as "rollCall" is called from the class rather than an instance, the code will work fine. If we try to call "rollCall" from an instance, e.g.:
rex.rollCall(-1)
however, it would cause an exception to be raised because it would send two arguments: itself and -1, and "rollCall" is only defined to accept one argument.
Incidentally, rex.rollCall() would send the correct number of arguments, but would also cause an exception to be raised because now n would be representing a Dog instance (i.e., rex) when the function expects n to be numerical.
This is where the decoration comes in:
If we precede the "rollCall" method with
#staticmethod
then, by explicitly stating that the method is static, we can even call it from an instance. Now,
rex.rollCall(-1)
would work. The insertion of #staticmethod before a method definition, then, stops an instance from sending itself as an argument.
You can verify this by trying the following code with and without the #staticmethod line commented out.
class Dog:
count = 0 # this is a class variable
dogs = [] # this is a class variable
def __init__(self, name):
self.name = name #self.name is an instance variable
Dog.count += 1
Dog.dogs.append(name)
def bark(self, n): # this is an instance method
print("{} says: {}".format(self.name, "woof! " * n))
#staticmethod
def rollCall(n):
print("There are {} dogs.".format(Dog.count))
if n >= len(Dog.dogs) or n < 0:
print("They are:")
for dog in Dog.dogs:
print(" {}".format(dog))
else:
print("The dog indexed at {} is {}.".format(n, Dog.dogs[n]))
fido = Dog("Fido")
fido.bark(3)
Dog.rollCall(-1)
rex = Dog("Rex")
Dog.rollCall(0)
rex.rollCall(-1)
Yes, check out the staticmethod decorator:
>>> class C:
... #staticmethod
... def hello():
... print "Hello World"
...
>>> C.hello()
Hello World
You don't really need to use the #staticmethod decorator. Just declaring a method (that doesn't expect the self parameter) and call it from the class. The decorator is only there in case you want to be able to call it from an instance as well (which was not what you wanted to do)
Mostly, you just use functions though...
Static methods in Python?
Is it possible to have static methods in Python so I can call them
without initializing a class, like:
ClassName.StaticMethod()
Yes, static methods can be created like this (although it's a bit more Pythonic to use underscores instead of CamelCase for methods):
class ClassName(object):
#staticmethod
def static_method(kwarg1=None):
'''return a value that is a function of kwarg1'''
The above uses the decorator syntax. This syntax is equivalent to
class ClassName(object):
def static_method(kwarg1=None):
'''return a value that is a function of kwarg1'''
static_method = staticmethod(static_method)
This can be used just as you described:
ClassName.static_method()
A builtin example of a static method is str.maketrans() in Python 3, which was a function in the string module in Python 2.
Another option that can be used as you describe is the classmethod, the difference is that the classmethod gets the class as an implicit first argument, and if subclassed, then it gets the subclass as the implicit first argument.
class ClassName(object):
#classmethod
def class_method(cls, kwarg1=None):
'''return a value that is a function of the class and kwarg1'''
Note that cls is not a required name for the first argument, but most experienced Python coders will consider it badly done if you use anything else.
These are typically used as alternative constructors.
new_instance = ClassName.class_method()
A builtin example is dict.fromkeys():
new_dict = dict.fromkeys(['key1', 'key2'])
Perhaps the simplest option is just to put those functions outside of the class:
class Dog(object):
def __init__(self, name):
self.name = name
def bark(self):
if self.name == "Doggy":
return barking_sound()
else:
return "yip yip"
def barking_sound():
return "woof woof"
Using this method, functions which modify or use internal object state (have side effects) can be kept in the class, and the reusable utility functions can be moved outside.
Let's say this file is called dogs.py. To use these, you'd call dogs.barking_sound() instead of dogs.Dog.barking_sound.
If you really need a static method to be part of the class, you can use the staticmethod decorator.
Aside from the particularities of how static method objects behave, there is a certain kind of beauty you can strike with them when it comes to organizing your module-level code.
# garden.py
def trim(a):
pass
def strip(a):
pass
def bunch(a, b):
pass
def _foo(foo):
pass
class powertools(object):
"""
Provides much regarded gardening power tools.
"""
#staticmethod
def answer_to_the_ultimate_question_of_life_the_universe_and_everything():
return 42
#staticmethod
def random():
return 13
#staticmethod
def promise():
return True
def _bar(baz, quux):
pass
class _Dice(object):
pass
class _6d(_Dice):
pass
class _12d(_Dice):
pass
class _Smarter:
pass
class _MagicalPonies:
pass
class _Samurai:
pass
class Foo(_6d, _Samurai):
pass
class Bar(_12d, _Smarter, _MagicalPonies):
pass
...
# tests.py
import unittest
import garden
class GardenTests(unittest.TestCase):
pass
class PowertoolsTests(unittest.TestCase):
pass
class FooTests(unittest.TestCase):
pass
class BarTests(unittest.TestCase):
pass
...
# interactive.py
from garden import trim, bunch, Foo
f = trim(Foo())
bunch(f, Foo())
...
# my_garden.py
import garden
from garden import powertools
class _Cowboy(garden._Samurai):
def hit():
return powertools.promise() and powertools.random() or 0
class Foo(_Cowboy, garden.Foo):
pass
It now becomes a bit more intuitive and self-documenting in which context certain components are meant to be used and it pans out ideally for naming distinct test cases as well as having a straightforward approach to how test modules map to actual modules under tests for purists.
I frequently find it viable to apply this approach to organizing a project's utility code. Quite often, people immediately rush and create a utils package and end up with 9 modules of which one has 120 LOC and the rest are two dozen LOC at best. I prefer to start with this and convert it to a package and create modules only for the beasts that truly deserve them:
# utils.py
class socket(object):
#staticmethod
def check_if_port_available(port):
pass
#staticmethod
def get_free_port(port)
pass
class image(object):
#staticmethod
def to_rgb(image):
pass
#staticmethod
def to_cmyk(image):
pass
So, static methods are the methods which can be called without creating the object of a class.
For Example :-
#staticmethod
def add(a, b):
return a + b
b = A.add(12,12)
print b
In the above example method add is called by the class name A not the object name.
Summarizing others' answers and adding, there are many ways to declare Static Methods or Variables in python.
Using staticmethod() as a decorator:
One can simply put a decorator above a method(function) declared to make it a static method. For eg.
class Calculator:
#staticmethod
def multiply(n1, n2, *args):
Res = 1
for num in args: Res *= num
return n1 * n2 * Res
print(Calculator.multiply(1, 2, 3, 4)) # 24
Using staticmethod() as a parameter function:
This method can receive an argument which is of function type, and it returns a static version of the function passed. For eg.
class Calculator:
def add(n1, n2, *args):
return n1 + n2 + sum(args)
Calculator.add = staticmethod(Calculator.add)
print(Calculator.add(1, 2, 3, 4)) # 10
Using classmethod() as a decorator:
#classmethod has similar effect on a function as #staticmethod has, but
this time, an additional argument is needed to be accepted in the function (similar to self parameter for instance variables). For eg.
class Calculator:
num = 0
def __init__(self, digits) -> None:
Calculator.num = int(''.join(digits))
#classmethod
def get_digits(cls, num):
digits = list(str(num))
calc = cls(digits)
return calc.num
print(Calculator.get_digits(314159)) # 314159
Using classmethod() as a parameter function:
#classmethod can also be used as a parameter function, in case one doesn't want to modify class definition. For eg.
class Calculator:
def divide(cls, n1, n2, *args):
Res = 1
for num in args: Res *= num
return n1 / n2 / Res
Calculator.divide = classmethod(Calculator.divide)
print(Calculator.divide(15, 3, 5)) # 1.0
Direct declaration
A method/variable declared outside all other methods, but inside a class is automatically static.
class Calculator:
def subtract(n1, n2, *args):
return n1 - n2 - sum(args)
print(Calculator.subtract(10, 2, 3, 4)) # 1
The whole program
class Calculator:
num = 0
def __init__(self, digits) -> None:
Calculator.num = int(''.join(digits))
#staticmethod
def multiply(n1, n2, *args):
Res = 1
for num in args: Res *= num
return n1 * n2 * Res
def add(n1, n2, *args):
return n1 + n2 + sum(args)
#classmethod
def get_digits(cls, num):
digits = list(str(num))
calc = cls(digits)
return calc.num
def divide(cls, n1, n2, *args):
Res = 1
for num in args: Res *= num
return n1 / n2 / Res
def subtract(n1, n2, *args):
return n1 - n2 - sum(args)
Calculator.add = staticmethod(Calculator.add)
Calculator.divide = classmethod(Calculator.divide)
print(Calculator.multiply(1, 2, 3, 4)) # 24
print(Calculator.add(1, 2, 3, 4)) # 10
print(Calculator.get_digits(314159)) # 314159
print(Calculator.divide(15, 3, 5)) # 1.0
print(Calculator.subtract(10, 2, 3, 4)) # 1
Refer to Python Documentation for mastering OOP in python.
Python Static methods can be created in two ways.
Using staticmethod()
class Arithmetic:
def add(x, y):
return x + y
# create add static method
Arithmetic.add = staticmethod(Arithmetic.add)
print('Result:', Arithmetic.add(15, 10))
Output:
Result: 25
Using #staticmethod
class Arithmetic:
# create add static method
#staticmethod
def add(x, y):
return x + y
print('Result:', Arithmetic.add(15, 10))
Output:
Result: 25
You can use #staticmethod decorator to define a static method as shown below. In detail, I explain about #staticmethod decorator and #classmethod decorator in my answer for #classmethod vs #staticmethod in Python and also explain about instance method in my answer for What is an "instance method" in Python?:
class Person:
#staticmethod # Here
def test():
print("Test")
I encounter this question from time to time. The use case and example that I am fond of is:
jeffs#jeffs-desktop:/home/jeffs $ python36
Python 3.6.1 (default, Sep 7 2017, 16:36:03)
[GCC 6.3.0 20170406] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import cmath
>>> print(cmath.sqrt(-4))
2j
>>>
>>> dir(cmath)
['__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atanh', 'cos', 'cosh', 'e', 'exp', 'inf', 'infj', 'isclose', 'isfinite', 'isinf', 'isnan', 'log', 'log10', 'nan', 'nanj', 'phase', 'pi', 'polar', 'rect', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'tau']
>>>
It does not make sense to create an object of class cmath, because there is no state in a cmath object. However, cmath is a collection of methods that are all related in some way. In my example above, all of the functions in cmath act on complex numbers in some way.

What's an example use case for a Python classmethod?

I've read What are Class methods in Python for? but the examples in that post are complex. I am looking for a clear, simple, bare-bones example of a particular use case for classmethods in Python.
Can you name a small, specific example use case where a Python classmethod would be the right tool for the job?
Helper methods for initialization:
class MyStream(object):
#classmethod
def from_file(cls, filepath, ignore_comments=False):
with open(filepath, 'r') as fileobj:
for obj in cls(fileobj, ignore_comments):
yield obj
#classmethod
def from_socket(cls, socket, ignore_comments=False):
raise NotImplemented # Placeholder until implemented
def __init__(self, iterable, ignore_comments=False):
...
Well __new__ is a pretty important classmethod. It's where instances usually come from
so dict() calls dict.__new__ of course, but there is another handy way to make dicts sometimes which is the classmethod dict.fromkeys()
eg.
>>> dict.fromkeys("12345")
{'1': None, '3': None, '2': None, '5': None, '4': None}
I don't know, something like named constructor methods?
class UniqueIdentifier(object):
value = 0
def __init__(self, name):
self.name = name
#classmethod
def produce(cls):
instance = cls(cls.value)
cls.value += 1
return instance
class FunkyUniqueIdentifier(UniqueIdentifier):
#classmethod
def produce(cls):
instance = super(FunkyUniqueIdentifier, cls).produce()
instance.name = "Funky %s" % instance.name
return instance
Usage:
>>> x = UniqueIdentifier.produce()
>>> y = FunkyUniqueIdentifier.produce()
>>> x.name
0
>>> y.name
Funky 1
The biggest reason for using a #classmethod is in an alternate constructor that is intended to be inherited. This can be very useful in polymorphism. An example:
class Shape(object):
# this is an abstract class that is primarily used for inheritance defaults
# here is where you would define classmethods that can be overridden by inherited classes
#classmethod
def from_square(cls, square):
# return a default instance of cls
return cls()
Notice that Shape is an abstract class that defines a classmethod from_square, since Shape is not really defined, it does not really know how to derive itself from a Square so it simply returns a default instance of the class.
Inherited classes are then allowed to define their own versions of this method:
class Square(Shape):
def __init__(self, side=10):
self.side = side
#classmethod
def from_square(cls, square):
return cls(side=square.side)
class Rectangle(Shape):
def __init__(self, length=10, width=10):
self.length = length
self.width = width
#classmethod
def from_square(cls, square):
return cls(length=square.side, width=square.side)
class RightTriangle(Shape):
def __init__(self, a=10, b=10):
self.a = a
self.b = b
self.c = ((a*a) + (b*b))**(.5)
#classmethod
def from_square(cls, square):
return cls(a=square.length, b=square.width)
class Circle(Shape):
def __init__(self, radius=10):
self.radius = radius
#classmethod
def from_square(cls, square):
return cls(radius=square.length/2)
The usage allows you to treat all of these uninstantiated classes polymorphically
square = Square(3)
for polymorphic_class in (Square, Rectangle, RightTriangle, Circle):
this_shape = polymorphic_class.from_square(square)
This is all fine and dandy you might say, but why couldn't I just use as #staticmethod to accomplish this same polymorphic behavior:
class Circle(Shape):
def __init__(self, radius=10):
self.radius = radius
#staticmethod
def from_square(square):
return Circle(radius=square.length/2)
The answer is that you could, but you do not get the benefits of inheritance because Circle has to be called out explicitly in the method. Meaning if I call it from an inherited class without overriding, I would still get Circle every time.
Notice what is gained when I define another shape class that does not really have any custom from_square logic:
class Hexagon(Shape):
def __init__(self, side=10):
self.side = side
# note the absence of classmethod here, this will use from_square it inherits from shape
Here you can leave the #classmethod undefined and it will use the logic from Shape.from_square while retaining who cls is and return the appropriate shape.
square = Square(3)
for polymorphic_class in (Square, Rectangle, RightTriangle, Circle, Hexagon):
this_shape = polymorphic_class.from_square(square)
I find that I most often use #classmethod to associate a piece of code with a class, to avoid creating a global function, for cases where I don't require an instance of the class to use the code.
For example, I might have a data structure which only considers a key valid if it conforms to some pattern. I may want to use this from inside and outside of the class. However, I don't want to create yet another global function:
def foo_key_is_valid(key):
# code for determining validity here
return valid
I'd much rather group this code with the class it's associated with:
class Foo(object):
#classmethod
def is_valid(cls, key):
# code for determining validity here
return valid
def add_key(self, key, val):
if not Foo.is_valid(key):
raise ValueError()
..
# lets me reuse that method without an instance, and signals that
# the code is closely-associated with the Foo class
Foo.is_valid('my key')
Another useful example of classmethod is in extending enumerated types. A classic Enum provides symbolic names which can be used later in the code for readability, grouping, type-safety, etc. This can be extended to add useful features using a classmethod. In the example below, Weekday is an enuerated type for the days of the week. It has been extended using classmethod so that instead of keeping track of the weekday ourselves, the enumerated type can extract the date and return the related enum member.
from enum import Enum
from datetime import date
class Weekday(Enum):
MONDAY = 1
TUESDAY = 2
WEDNESDAY = 3
THURSDAY = 4
FRIDAY = 5
SATURDAY = 6
SUNDAY = 7
#
#classmethod
def from_date(cls, date):
return cls(date.isoweekday())
Weekday.from_date(date.today())
<Weekday.TUESDAY: 2>
Source: https://docs.python.org/3/howto/enum.html
in class MyClass(object):
'''
classdocs
'''
obj=0
x=classmethod
def __init__(self):
'''
Constructor
'''
self.nom='lamaizi'
self.prenom='anas'
self.age=21
self.ville='Casablanca'
if __name__:
ob=MyClass()
print(ob.nom)
print(ob.prenom)
print(ob.age)
print(ob.ville)

Categories

Resources