How to call a subclass, for example, class1.class2.function, just like subdomains, shop.domain.com i tried this method
class A:
class B:
def ping():
print("Hi")
a = A()
b = a.B()
but it didn't work.
i also tried
class A:
def ping():
print("Class A")
class B(A):
def pingB():
print("Class B")
but also didn't work
You didn't add the self argument-
IN FIRST CASE:
class A:
class B:
def ping(self):
print("Hi")
a = A()
b = a.B()
b.ping()
IN SECOND CASE:
class A:
def ping():
print("Class A")
class B(A):
def pingB(self):
print("Class B")
b = B()
b.pingB()
Hope so this information is useful to you!
Happy Coding!
You still need to call the function within the B class when initializing b as the subclass B. Also, functions within a class need the self parameter.
class A:
class B:
def ping(self):
print("Hi")
a = A() # Initializing variable <a> as new object to class <A>
b = a.B() # Initializing variable <b> as new object to class <B> (Subclass of a)
b.ping() # Calling function <ping> which should print the string "Hi"
I want to make a class A like this
class A:
#someDecorator
def f(self):
print('A.f')
def g(self):
print('A.g')
And I can use it like this
a = A()
a.f() #prints A.f
a.g() #prints A.g
But if I declare a class B as a subclass of A, attribute f of class B will become invisible
class B(A):
pass
b = B()
b.g() #prints A.g
b.f() #error: no such attribute
How can I make this #someDecorator?
One way is to check __class__ of the method, and return if it matches A.
def disable_method(func):
def func_wrapper(name):
if name.__class__ == A:
return func(name)
else:
raise AttributeError("Cannot call inherited method")
return func_wrapper
class A:
#disable_method
def f(self):
print('A.f')
def g(self):
print('A.g')
class B(A):
pass
a = A()
a.f()
#A.f
b = B()
b.f()
#AttributeError: Cannot call inherited method
Edit: Looking at this again it is possible to check whether the method's class has a superclass by __bases__. It should work as long as its being used as a decorator.
def disable_method(func):
def func_wrapper(name):
if name.__class__.__bases__ == object:
return func(name)
else:
raise AttributeError("Cannot call method from superclass")
return func_wrapper
class A(object):
__A = None
def get_a(self):
return self.__A
def set_a(self, value):
self.__A = value
class B(A):
def method_b(self, value):
self.set_a(value)
class C(A):
def method_c(self)
self.get_a()
Someone can to explain me how can i to catch installed value in method_b inside my 'C' class method?
P.S. In this variant i just getting nothing.
Python isn't Java; you don't need setters & getters here: just access the attributes directly.
There are three problems with your code.
C.method_c() has no return statement, so it returns None.
You are using __ name mangling when that's exactly what you don't want.
In A.set_a() you want to set a class attribute, but your assignment instead creates an instance attribute which shadows the class attribute.
Here's a repaired version.
class A(object):
_A = 'nothing'
def get_a(self):
return self._A
def set_a(self, value):
A._A = value
class B(A):
def method_b(self, value):
self.set_a(value)
class C(A):
def method_c(self):
return self.get_a()
b = B()
c = C()
print(c.method_c())
b.method_b(13)
print(c.method_c())
output
nothing
13
Here's a slightly more Pythonic version:
class A(object):
_A = 'nothing'
class B(A):
def method_b(self, value):
A._A = value
class C(A):
pass
b = B()
c = C()
print(c._A)
b.method_b(13)
print(c._A)
I want to add some attributes and methods into various class. The methods and attributes that I have to add are the same but not the class to assign them, so I want to construct a class who assign new methods and attributes for a class given in argument.
I try this but it's not working:
(I know that is a very wrong way to try to assign something to self, it's just to show what I want to do)
class A:
def __init__(self):
self.a = 'a'
def getattA(self):
return self.a
class B:
def __init__(self, parent) :
self = parent
# This is working :
print self.getattA()
def getattB(self):
return self.getattA()
insta = A()
instb = B(insta)
# This is not working :
print instb.getattB()
The result is :
a
Traceback (most recent call last):
File "D:\Documents and settings\Bureau\merge.py", line 22, in <module>
print instb.getattB()
File "D:\Documents and settings\Bureau\merge.py", line 16, in getattB
return self.getattA()
AttributeError: B instance has no attribute 'getattA'
And I expected to got 'a' for the call of instb.gettattB()
To resume I want to inherit class B from class A giving class A in argument of class B because my class B will be a subclass of various class, not always A.
The Best answer is in the comments, it was useful for me so I decided to show it in an answer (thank to sr2222):
The way to dynamicaly declare inherance in Python is the type() built-in function.
For my example :
class A(object) :
def __init__(self, args):
self.a = 'a'
self.args = args
def getattA(self):
return self.a, self.args
class B(object) :
b = 'b'
def __init__(self, args) :
self.b_init = args
def getattB(self):
return self.b
C = type('C', (A,B), dict(c='c'))
instc = C('args')
print 'attributes :', instc.a, instc.args, instc.b, instc.c
print 'methodes :', instc.getattA(), instc.getattB()
print instc.b_init
The code return :
attributes : a args b c
methodes : ('a', 'args') b
Traceback (most recent call last):
File "D:\Documents and settings\Bureau\merge2.py", line 24, in <module>
print instc.b_init
AttributeError: 'C' object has no attribute 'b_init'
My class C inerhite attributes and methods of class A and class B and we add c attribute. With the instanciation of C (instc = C('args')) The init for A is call but not for B.
Very useful for me because I have to add some attributes and methodes (the same) on different class.
I was having trouble with calling different constructors, using super doesn't necessarily make sense in a case like this, I opted to inherit and call each constructor on the current object manually:
class Foo(object):
def __init__(self, foonum):
super(Foo, self).__init__()
self.foonum = foonum
class Bar(object):
def __init__(self, barnum):
super(Bar, self).__init__()
self.barnum = barnum
class DiamondProblem(Foo, Bar):
# Arg order don't matter, since we call the `__init__`'s ourself.
def __init__(self, barnum, mynum, foonum):
Foo.__init__(self, foonum)
Bar.__init__(self, barnum)
self.mynum = mynum
How about this?
class A:
def __init__(self):
self.a = 'a'
def getatt(self):
return self.a
class B:
def __init__(self, parent) :
self.parent = parent
def __getattr__(self, attr):
return getattr(self.parent, attr)
def getattB(self):
return self.parent.getatt()
insta = A()
instb = B(insta)
print instb.getattB()
print instb.getatt()
But method in class A can not access attr in class B.
Another way:
import functools
class A:
def __init__(self):
self.a = 'a'
def getatt(self):
return self.a
class B:
def __init__(self, parent):
for attr, val in parent.__dict__.iteritems():
if attr.startswith("__"): continue
self.__dict__[attr] = val
for attr, val in parent.__class__.__dict__.iteritems():
if attr.startswith("__"): continue
if not callable(val): continue
self.__dict__[attr] = functools.partial(val, self)
def getattB(self):
return self.getatt()
insta = A()
instb = B(insta)
print instb.__dict__
print instb.getattB()
print instb.getatt()
Slow with init but call fast.
Since B is not a subclass of A, there is no path in B to getatt() in A
I guess i have a easier method
class fruit1:
def __init__(self):
self.name = "apple"
self.color = "blue"
class fruit2:
def __init__(self):
self.name = "banana"
self.size = 100
def merge(ob1, ob2):
ob1.__dict__.update(ob2.__dict__)
return ob1
f1 = fruit1()
f2 = fruit2()
fruit = merge(f1, f2)
print("name:",fruit.name," color:",fruit.color, " size:",fruit.size)
#output: name: banana color: blue size: 100
I'm not certain what you are trying to do, but the code below is giving my the output I think you are expecting. notice:
a is initialized outside the constructor in A
B is declared as a subclass of A
Code:
class A:
a='' #Initialize a
def __init__(self):
self.a = 'a'
def getatt(self):
return self.a
class B(A): #Declare B as subclass
def __init__(self, parent) :
self = parent
print self.getatt()
def getattB(self):
return self.getatt()
insta = A()
instb = B(insta)
print instb.getattB()
Helper function below conducts the merge of the dataclass instances, the attributes orders is derived from *args order:
from dataclasses import dataclass
#dataclass
class A:
foo: str
bar: str
def merge_dataclasses(*args):
if len({e.__class__.__name__ for e in args}) > 1:
raise NotImplementedError('Merge of non-homogeneous entries no allowed.')
data = {}
for entry in args[::-1]:
data.update(vars(entry))
return entry.__class__(**data)
print(merge_dataclasses(A(foo='f', bar='bar'), A(foo='b_foo', bar='b_bar')))
One easy way to merge two or more classes is through the tool set dyndesign:
from dyndesign import mergeclasses
class Base:
def __init__(self, init_value):
self.param = init_value
def m1(self):
print(f"Method `m1` of class `Base`, and {self.param=}")
def m2(self):
print(f"Method `m2` of class `Base`")
class Ext:
def m1(self):
print(f"Method `m1` of class `Ext`, and {self.param=}")
MergedClass = mergeclasses(Base, Ext)
merged_instance = MergedClass("INITIAL VALUE")
merged_instance.m1()
# Method `m1` of class `Ext`, and self.param='INITIAL VALUE'
merged_instance.m2()
# Method `m2` of class `Base`
Emphasizing ThorSummoner's's answer and Hong's comment; this method appears to be cleaner than the excepted answer. Notice Hong's use of super().init(self) in all but the last object added to the merge class.
class Foo(object):
def __init__(self, foonum):
super(Foo, self).__init__(self)
self.foonum = foonum
class Bar(object):
def __init__(self, barnum):
super(Bar, self).__init__(self)
self.barnum = barnum
class Oops(object):
def __init__(self, oopsnum):
super(Oops, self).__init__()
self.oopsnum = oopsnum
class DiamondProblem(Foo, Bar, Oops):
def __init__(self, mynum, foonum, barnum, oopsnum):
Foo.__init__(self, foonum)
Bar.__init__(self, barnum)
Oops.__init__(self, oopsnum)
self.mynum = mynum
def main():
dia = DiamondProblem(1, 10, 20, 30)
print(f"mynum: {dia.mynum}")
print(f"foonum: {dia.foonum}")
print(f"barnum: {dia.barnum}")
print(f"oopsnum: {dia.oopsnum}")
I have a code (simplified):
class A(object):
attrib1 = "a"
attrib2 = "b"
class B(A):
flag = True
in some place in my code, I have an instance of A, but I need to create an instance of class B, which will have all the data from instance of A... I feel myself stupid, but I don't want to do something like:
class B(A):
def __init__(self,a1,a2,a3,a4,..):
self.a1 = a1
self.a2 = a2
and call like:
obj_b = B( obj_a.a1, obj_a.a2,...)
class B(A):
def __init__(self, obj):
self.__dict__.update(obj.__dict__)
Another option is to change the __class__ variable on your instance of A.
a = A()
a.__class__ = B