In Python, how do you make a subclass from a superclass?
# Initialize using Parent
#
class MySubClass(MySuperClass):
def __init__(self):
MySuperClass.__init__(self)
Or, even better, the use of Python's built-in function, super() (see the Python 2/Python 3 documentation for it) may be a slightly better method of calling the parent for initialization:
# Better initialize using Parent (less redundant).
#
class MySubClassBetter(MySuperClass):
def __init__(self):
super(MySubClassBetter, self).__init__()
Or, same exact thing as just above, except using the zero argument form of super(), which only works inside a class definition:
class MySubClassBetter(MySuperClass):
def __init__(self):
super().__init__()
A heroic little example:
class SuperHero(object): #superclass, inherits from default object
def getName(self):
raise NotImplementedError #you want to override this on the child classes
class SuperMan(SuperHero): #subclass, inherits from SuperHero
def getName(self):
return "Clark Kent"
class SuperManII(SuperHero): #another subclass
def getName(self):
return "Clark Kent, Jr."
if __name__ == "__main__":
sm = SuperMan()
print(sm.getName())
sm2 = SuperManII()
print(sm2.getName())
class MySubClass(MySuperClass):
def __init__(self):
MySuperClass.__init__(self)
# <the rest of your custom initialization code goes here>
The section on inheritance in the python documentation explains it in more detail
class Class1(object):
pass
class Class2(Class1):
pass
Class2 is a sub-class of Class1
In the answers above, the super is initialized without any (keyword) arguments. Often, however, you would like to do that, as well as pass on some 'custom' arguments of your own. Here is an example which illustrates this use case:
class SortedList(list):
def __init__(self, *args, reverse=False, **kwargs):
super().__init__(*args, **kwargs) # Initialize the super class
self.reverse = reverse
self.sort(reverse=self.reverse) # Do additional things with the custom keyword arguments
This is a subclass of list which, when initialized, immediately sorts itself in the direction specified by the reverse keyword argument, as the following tests illustrate:
import pytest
def test_1():
assert SortedList([5, 2, 3]) == [2, 3, 5]
def test_2():
SortedList([5, 2, 3], reverse=True) == [5, 3, 2]
def test_3():
with pytest.raises(TypeError):
sorted_list = SortedList([5, 2, 3], True) # This doesn't work because 'reverse' must be passed as a keyword argument
if __name__ == "__main__":
pytest.main([__file__])
Thanks to the passing on of *args to super, the list can be initialized and populated with items instead of only being empty. (Note that reverse is a keyword-only argument in accordance with PEP 3102).
There is another way to make subclasses in python dynamically with a function type():
SubClass = type('SubClass', (BaseClass,), {'set_x': set_x}) # Methods can be set, including __init__()
You usually want to use this method when working with metaclasses. When you want to do some lower level automations, that alters way how python creates class. Most likely you will not ever need to do it in this way, but when you do, than you already will know what you are doing.
class Subclass (SuperClass):
# Subclass stuff here
You use:
class DerivedClassName(BaseClassName):
For details, see the Python docs, section 9.5.
class Mammal(object):
#mammal stuff
class Dog(Mammal):
#doggie stuff
Subclassing in Python is done as follows:
class WindowElement:
def print(self):
pass
class Button(WindowElement):
def print(self):
pass
Here is a tutorial about Python that also contains classes and subclasses.
class BankAccount:
def __init__(self, balance=0):
self.balance = int(balance)
def checkBalance(self): ## Checking opening balance....
return self.balance
def deposit(self, deposit_amount=1000): ## takes in cash deposit amount and updates the balance accordingly.
self.deposit_amount = deposit_amount
self.balance += deposit_amount
return self.balance
def withdraw(self, withdraw_amount=500): ## takes in cash withdrawal amount and updates the balance accordingly
if self.balance < withdraw_amount: ## if amount is greater than balance return `"invalid transaction"`
return 'invalid transaction'
else:
self.balance -= withdraw_amount
return self.balance
class MinimumBalanceAccount(BankAccount): #subclass MinimumBalanceAccount of the BankAccount class
def __init__(self,balance=0, minimum_balance=500):
BankAccount.__init__(self, balance=0)
self.minimum_balance = minimum_balance
self.balance = balance - minimum_balance
#print "Subclass MinimumBalanceAccount of the BankAccount class created!"
def MinimumBalance(self):
return self.minimum_balance
c = BankAccount()
print(c.deposit(50))
print(c.withdraw(10))
b = MinimumBalanceAccount(100, 50)
print(b.deposit(50))
print(b.withdraw(10))
print(b.MinimumBalance())
this is a small code:
# create a parent class
class Person(object):
def __init__(self):
pass
def getclass(self):
return 'I am a Person'
# create two subclass from Parent_class
class Student(Person):
def __init__(self):
super(Student, self).__init__()
def getclass(self):
return 'I am a student'
class Teacher(Person):
def __init__(self):
super(Teacher, self).__init__()
def getclass(self):
return 'I am a teacher'
person1 = Person()
print(person1.getclass())
student1 = Student()
print(student1.getclass())
teacher1 = Teacher()
print(teacher1.getclass())
show result:
I am a Person
I am a student
I am a teacher
A minor addition to #thompsongunner's answer.
To pass args to your superclass (parent), just use the function signature of the parent class:
class MySubClassBetter(MySuperClass):
def __init__(self, someArg, someKwarg="someKwarg"):
super().__init__(someArg, someKwarg=someKwarg)
You are calling the parent's __init__() method as if you are constructing any other class which is why you don't need to include self.
Related
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()
When creating a simple object hierarchy in Python, I'd like to be able to invoke methods of the parent class from a derived class. In Perl and Java, there is a keyword for this (super). In Perl, I might do this:
package Foo;
sub frotz {
return "Bamf";
}
package Bar;
#ISA = qw(Foo);
sub frotz {
my $str = SUPER::frotz();
return uc($str);
}
In Python, it appears that I have to name the parent class explicitly from the child.
In the example above, I'd have to do something like Foo::frotz().
This doesn't seem right since this behavior makes it hard to make deep hierarchies. If children need to know what class defined an inherited method, then all sorts of information pain is created.
Is this an actual limitation in python, a gap in my understanding or both?
Use the super() function:
class Foo(Bar):
def baz(self, **kwargs):
return super().baz(**kwargs)
For Python < 3, you must explicitly opt in to using new-style classes and use:
class Foo(Bar):
def baz(self, arg):
return super(Foo, self).baz(arg)
Python also has super as well:
super(type[, object-or-type])
Return a proxy object that delegates method calls to a parent or sibling class of type.
This is useful for accessing inherited methods that have been overridden in a class.
The search order is same as that used by getattr() except that the type itself is skipped.
Example:
class A(object): # deriving from 'object' declares A as a 'new-style-class'
def foo(self):
print "foo"
class B(A):
def foo(self):
super(B, self).foo() # calls 'A.foo()'
myB = B()
myB.foo()
ImmediateParentClass.frotz(self)
will be just fine, whether the immediate parent class defined frotz itself or inherited it. super is only needed for proper support of multiple inheritance (and then it only works if every class uses it properly). In general, AnyClass.whatever is going to look up whatever in AnyClass's ancestors if AnyClass doesn't define/override it, and this holds true for "child class calling parent's method" as for any other occurrence!
Python 3 has a different and simpler syntax for calling parent method.
If Foo class inherits from Bar, then from Bar.__init__ can be invoked from Foo via super().__init__():
class Foo(Bar):
def __init__(self, *args, **kwargs):
# invoke Bar.__init__
super().__init__(*args, **kwargs)
Many answers have explained how to call a method from the parent which has been overridden in the child.
However
"how do you call a parent class's method from child class?"
could also just mean:
"how do you call inherited methods?"
You can call methods inherited from a parent class just as if they were methods of the child class, as long as they haven't been overwritten.
e.g. in python 3:
class A():
def bar(self, string):
print("Hi, I'm bar, inherited from A"+string)
class B(A):
def baz(self):
self.bar(" - called by baz in B")
B().baz() # prints out "Hi, I'm bar, inherited from A - called by baz in B"
yes, this may be fairly obvious, but I feel that without pointing this out people may leave this thread with the impression you have to jump through ridiculous hoops just to access inherited methods in python. Especially as this question rates highly in searches for "how to access a parent class's method in Python", and the OP is written from the perspective of someone new to python.
I found:
https://docs.python.org/3/tutorial/classes.html#inheritance
to be useful in understanding how you access inherited methods.
Here is an example of using super():
#New-style classes inherit from object, or from another new-style class
class Dog(object):
name = ''
moves = []
def __init__(self, name):
self.name = name
def moves_setup(self):
self.moves.append('walk')
self.moves.append('run')
def get_moves(self):
return self.moves
class Superdog(Dog):
#Let's try to append new fly ability to our Superdog
def moves_setup(self):
#Set default moves by calling method of parent class
super(Superdog, self).moves_setup()
self.moves.append('fly')
dog = Superdog('Freddy')
print dog.name # Freddy
dog.moves_setup()
print dog.get_moves() # ['walk', 'run', 'fly'].
#As you can see our Superdog has all moves defined in the base Dog class
There's a super() in Python too. It's a bit wonky, because of Python's old- and new-style classes, but is quite commonly used e.g. in constructors:
class Foo(Bar):
def __init__(self):
super(Foo, self).__init__()
self.baz = 5
I would recommend using CLASS.__bases__
something like this
class A:
def __init__(self):
print "I am Class %s"%self.__class__.__name__
for parentClass in self.__class__.__bases__:
print " I am inherited from:",parentClass.__name__
#parentClass.foo(self) <- call parents function with self as first param
class B(A):pass
class C(B):pass
a,b,c = A(),B(),C()
If you don't know how many arguments you might get, and want to pass them all through to the child as well:
class Foo(bar)
def baz(self, arg, *args, **kwargs):
# ... Do your thing
return super(Foo, self).baz(arg, *args, **kwargs)
(From: Python - Cleanest way to override __init__ where an optional kwarg must be used after the super() call?)
There is a super() in python also.
Example for how a super class method is called from a sub class method
class Dog(object):
name = ''
moves = []
def __init__(self, name):
self.name = name
def moves_setup(self,x):
self.moves.append('walk')
self.moves.append('run')
self.moves.append(x)
def get_moves(self):
return self.moves
class Superdog(Dog):
#Let's try to append new fly ability to our Superdog
def moves_setup(self):
#Set default moves by calling method of parent class
super().moves_setup("hello world")
self.moves.append('fly')
dog = Superdog('Freddy')
print (dog.name)
dog.moves_setup()
print (dog.get_moves())
This example is similar to the one explained above.However there is one difference that super doesn't have any arguments passed to it.This above code is executable in python 3.4 version.
In this example cafec_param is a base class (parent class) and abc is a child class. abc calls the AWC method in the base class.
class cafec_param:
def __init__(self,precip,pe,awc,nmonths):
self.precip = precip
self.pe = pe
self.awc = awc
self.nmonths = nmonths
def AWC(self):
if self.awc<254:
Ss = self.awc
Su = 0
self.Ss=Ss
else:
Ss = 254; Su = self.awc-254
self.Ss=Ss + Su
AWC = Ss + Su
return self.Ss
def test(self):
return self.Ss
#return self.Ss*4
class abc(cafec_param):
def rr(self):
return self.AWC()
ee=cafec_param('re',34,56,2)
dd=abc('re',34,56,2)
print(dd.rr())
print(ee.AWC())
print(ee.test())
Output
56
56
56
In Python 2, I didn't have a lot luck with super(). I used the answer from
jimifiki on this SO thread how to refer to a parent method in python?.
Then, I added my own little twist to it, which I think is an improvement in usability (Especially if you have long class names).
Define the base class in one module:
# myA.py
class A():
def foo( self ):
print "foo"
Then import the class into another modules as parent:
# myB.py
from myA import A as parent
class B( parent ):
def foo( self ):
parent.foo( self ) # calls 'A.foo()'
class department:
campus_name="attock"
def printer(self):
print(self.campus_name)
class CS_dept(department):
def overr_CS(self):
department.printer(self)
print("i am child class1")
c=CS_dept()
c.overr_CS()
If you want to call the method of any class, you can simply call Class.method on any instance of the class. If your inheritance is relatively clean, this will work on instances of a child class too:
class Foo:
def __init__(self, var):
self.var = var
def baz(self):
return self.var
class Bar(Foo):
pass
bar = Bar(1)
assert Foo.baz(bar) == 1
class a(object):
def my_hello(self):
print "hello ravi"
class b(a):
def my_hello(self):
super(b,self).my_hello()
print "hi"
obj = b()
obj.my_hello()
This is a more abstract method:
super(self.__class__,self).baz(arg)
A derived class has access to its base class member functions implicitly, unless I am mistaken. A derived class can also access its base class' attributes by prefixing a call to them like this: BaseClass.base_attribute. But I seemingly do not understand how instances of a derived class can use the methods of the base class. Example:
class Visitor():
""" Interface to Visitor
provide an interface to visitors that
perform an operation on a data collection """
def visitProduce():
pass
def visitMeat():
pass
def visitBakedGoods():
pass
def visitDairy():
pass
def visitNonFood():
pass
class PriceVisitor(Visitor):
__cost = 0.0 # total cost of groceries
def __init__(self):
self.__cost = 0.0
def visitProduce(self, p):
self.__cost += p.price()
def visitMeat(self, m):
self.__cost += m.price()
def visitBakedGoods(self, b):
self.__cost += b.price()
def visitDairy(self, d):
self.__cost += d.price()
def visitNonFood(self, nf):
self.__cost += nf.price()
class Groceries():
shopping_cart = [] # list of grocery items
def Groceries(self):
self.shopping_cart = []
def addProduce(self, p):
pass
def addMeat(self, m, lb):
pass
def addBakedGoods(self, b):
pass
def addDairy(self, d):
pass
def addNonFood(self, nf):
pass
def accept(self, v):
pass
def getShoppingCart(self):
print(self.shopping_cart)
def calculateCost(self, v):
for item in self.shopping_cart:
item.accept(v)
item.details()
print('Total cost is: $', v.__cost)
class Produce(Groceries):
def addProduce(self):
Groceries.shopping_cart.append(self)
def accept(self, v):
v.visitProduce(self)
def price(self):
return self.__price
def details(self):
print(self.__name, ' for: $', self.__price + '')
class Apples(Produce):
__name = None
__price = 3.25
def __init__(self, name):
self.__name = name
And here is a test of the Apple, Produce, Groceries, and PriceVisitor classes
import VisitorPattern as vp
def main():
# Visitor object
my_visitor = vp.PriceVisitor()
# Grocery object stores objects in its shopping_cart attribute
my_groceries = vp.Groceries()
# Add items
red_apple = vp.Apples('red apple')
gold_apple = vp.Apples('gold apple')
red_apple.addProduce()
gold_apple.addProduce()
my_groceries.getShoppingCart()
my_groceries.calculateCost(my_visitor)
if __name__ == '__main__':
main()
Now, the way I understand it is that upon the construction of the instance of Apple, it has access to Produce's method price(). Calling this method with an instance of the Apple class will then pass its own instance in place of the 'self'. The program then returns the value of the __price attribute belonging to the instance calling the method, in this case Apple. However, I get this error:
C:\Users\josep_000\Documents\School\Summer 2015\Python Assignment 4>python test.
py
[<VisitorPattern.Apples object at 0x026E0830>, <VisitorPattern.Apples object at
0x026E0910>]
Traceback (most recent call last):
File "test.py", line 23, in <module>
main()
File "test.py", line 20, in main
my_groceries.calculateCost(my_visitor)
File "C:\Users\josep_000\Documents\School\Summer 2015\Python Assignment 4\Visi
torPattern.py", line 60, in calculateCost
item.accept(v)
File "C:\Users\josep_000\Documents\School\Summer 2015\Python Assignment 4\Visi
torPattern.py", line 71, in accept
v.visitProduce(self)
File "C:\Users\josep_000\Documents\School\Summer 2015\Python Assignment 4\Visi
torPattern.py", line 28, in visitProduce
self.__cost += p.price()
File "C:\Users\josep_000\Documents\School\Summer 2015\Python Assignment 4\Visi
torPattern.py", line 74, in price
return self.__price
AttributeError: 'Apples' object has no attribute '_Produce__price'
How does the binding and namespaces actually work in inheritance? I could just write the price() method in each of Produce's derived classes, but that would defeat the point of inheritance. I think my problem also stems from name mangling, but still don't know what happens if I don't make my attributes 'private'. Clarification would be great. Thanks
Edit
I declared the constructor of Groceries wrong:
# Wrong way
def Groceries(self):
self.shopping_cart = []
# Should be
def __init__(self):
self.__shopping_cart = []
The product of a full time job and homework in the evening
What is the order of namespaces in inheritance?
Python uses the Method Resolution Order to find the method bound to that instance of the object.
It also invokes name mangling, which is why you can't find the method, _Produce__price. You're trying to use .__price but when it is inherited, Python adds the name of the class to the front of the name. Don't use two underscores, change the two underscores to one, and your code will work as you expect, and you'll consistently look up ._price which won't invoke the name mangling.
See the docs for more on this:
https://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references
Not really a direct answer to all your questions but I hope the following code sheds some light on how to do inheritance in Python.
class Produce(object):
def __init__(self, name=None, price=None):
self.__name = name
self.__price = price
def __str__(self):
return self.__name
#property
def bulk_price(self):
return self.__price * 100
class Apple(Produce):
def __init__(self, name="Apple"):
self.__name = name
self.__price = 3.25
super(self.__class__, self).__init__(self.__name, self.__price)
a = Apple("Gold Apple")
print a
print a.bulk_price
# Gold Apple
# 325.0
As you can see, I made name and price inaccessible in both classes. This way, I cannot just call them explicitly, i.e. a.__price. By using super as well in the child class, I am able to avoid referring to the base class further while still having access to its methods.
I have saw your error, your parent need to call child's function, but you have not transferred child to parent, so it will get the errors.Now I give my example:
class A:
def __init__(self, handler):
self.a = 5
self.real_handler = handler
def get(self):
print "value a = %d"%self.a
self.real_handler.put()
class B(A):
def __init__(self):
A.__init__(self, self) ##transport B to A
self.b = 3
def get(self):
print "value b is %d"%self.b
A.get(self)
def put(self):
self.b = 6
print "value b change into %d"%self.b
if __name__=="__main__":
b = B()
b.get()
In parent B, it will call the child A's fuction put(). I hope this can help you.
I am trying to call a static method inside a class to populate the class variable.
import sys
import os
from HelpingData import *
class Inventory(object):
shipping_cost = 400.0
total_stock = calculate_total_stock.__func__()
def __init__(self, attributes={}):
self.inventory = {}
if attributes is None:
self.inventory = {}
else:
for key in attributes:
self.inventory[key] = attributes[key]
def getValue(self,attribute):
return self.inventory[attribute]
def setValue(self,attribute,value):
self.inventory[attribute]=value
#staticmethod
def calculate_total_stock():
total_stock = dict((item, 0) for item in product_names)
for nation in product_stock:
for item in nation:
total_stock[item] += nation[item]
return total_stock
And this is the error I am getting:
total_stock = calculate_total_stock.__func__()
NameError: name'calculate_total_stock' is not defined
What am I missing here?
You really don't need any workaround here, just give the calling method an additional level of direction.
In the example below you can call the PrintThis() method both internal and external to its defining class.
External:
Call as you normally would
MyClass.PrintThis('42')
Internal:
You must add self or the containing class
MyClass.PrintThis('42')
self.PrintThis('42')
To produce the error:
class MyClass:
def __init__(self):
self.MyValue = 0
def IncrementValue(self):
self.MyValue += 1
PrintThis(f'From MyClass {self.MyValue}')
#staticmethod
def PrintThis(arg):
print(f'My Value: {arg}')
The Fix:
class MyClass:
def __init__(self):
self.MyValue = 0
def IncrementValue(self):
self.MyValue += 1
self.PrintThis(f'From MyClass {self.MyValue}')
#staticmethod
def PrintThis(arg):
print(f'My Value: {arg}')
Run It
class Run:
def __init__(self):
mc = MyClass()
MyClass.PrintThis('From Outside')
mc.IncrementValue()
mc.IncrementValue()
My Value: From Outside
My Value: From MyClass 1
My Value: From MyClass 2
Why?
I'm not sure :-)
The only thing I noticed is that the static method (PrintThis) is a function, while the non-static method is a bound method.
I am sure there is some explanation to this behavior in Pythons documentation. Please share if you look it up :-)
I know this question is a few years old at this point, however it was the first hit when I googled the fault.
The code at the top level of the Inventory definition (i.e. class attributes and method definitions) runs before the name Inventory exists, so you can't call its own methods within the definition. As you have a #staticmethod, which doesn't require any class or instance argument, why not move it outside?
def calculate_total_stock(product_names, product_stock):
total_stock = dict((item, 0) for item in product_names)
for nation in product_stock:
for item in nation:
total_stock[item] += nation[item]
return total_stock
class Inventory(object):
SHIPPING_COST = 400.0
TOTAL_STOCK = calculate_total_stock(product_names, product_stock)
def __init__(self, attributes=None):
self.inventory = {}
if attributes is not None:
for key in attributes:
self.inventory[key] = attributes[key]
def get_value(self, attribute):
return self.inventory[attribute]
def set_value(self, attribute, value):
self.inventory[attribute] = value
Note that I have done some tidying up, particularly in terms of style and making the explicit arguments to calculate_total_stock.
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)