Static inheritance python - python

I'm trying to make some kind of static inheritance happen.
The code below prints "nope".
I'm not sure how to explain myself but what I want is that
class A uses B's method if it exists.
class A(object):
#staticmethod
def test():
print("nope")
#staticmethod
def test2():
__class__.test()
class B(A):
#staticmethod
def test():
print("It Works")
#staticmethod
def run():
__class__.test2()
if __name__ == "__main__":
B.run()

__class__ as a closure reference was never meant to be used as a reference to the current instance type; it'll always refer to the class you defined a method on (e.g. A for A.test2). It is a internal implementation detail used by the super() function. Don't use it here.
Use #classmethod instead;
class A(object):
#classmethod
def test(cls):
print("nope")
#classmethod
def test2(cls):
cls.test()
class B(A):
#classmethod
def test(cls):
print("It Works")
#classmethod
def run(cls):
cls.test2()
if __name__ == "__main__":
B.run()

Related

Can't get method name when using decorator

I suppose I'm missing something obvious, but I can't get the name of methods when I'm using decorators. When I run this code, I get the error:
AttributeError: 'str' object has no attribute "__name__"
Could somebody tell me how I can get the name of these decorated method?
Thanks
def Print(*arg, **kwarg):
func, *arguments = arg
print(func.__name__ + "(): {}".format(func=arguments[0]))
class Bob(object):
def __init__(self):
pass
#property
def stuff(self):
return "value from stuff property"
#stuff.setter
def stuff(self, noise):
return noise
class Tester:
def __init__(self):
self.dylan = Bob()
def randomTest(self):
Print(self.dylan.stuff, 1)
if __name__ == "__main__":
whatever = Tester()
whatever.randomTest()
stuff isn't a function or a method; it's a property. The syntax
#property
def stuff(...):
...
creates an instance of the property class using stuff as the argument to property, equivalent to
def stuff(...):
....
stuff = property(stuff)
and instances of property don't have a __name__ attribute, as you've seen.
(It's a little trickier with the setter, since the function and the property have to have the same name. But defining stuff a "second" time doesn't override the existing property named stuff.)
The individual methods are accessed via attributes of the property.
>>> Bob.stuff.fget.__name__
'stuff'
>>> Bob.stuff.fset.__name__
'stuff'
Note another, longer, way to create the same property:
class Bob:
def stuff_getter(self):
...
def stuff_setter(self, noise):
...
stuff = property(stuff_getter, stuff_setter)
del stuff_getter, stuff_setter # Clean up the namespace
def Print(*arg, **kwarg):
func, *arguments = arg
print(func.__name__ + "(): {}".format(func=arguments[0]))
class Bob():
def __init__(self, s):
self.stuff = s
#property
def myStuff(self):
return self.stuff
#myStuff.setter
def setStuff(self, noise):
self.stuff = noise
class Tester:
def __init__(self):
self.dylan = Bob(1)
def randomTest(self):
print(self.dylan.stuff)
if __name__ == "__main__":
whatever = Tester()
whatever.randomTest()
This should work :)

Why do I need to call 'self' in this case?

I am new to OOP and I am wondering why I need to supply the parameter MainWindow to the final line. If I call outside_func by itself, I don't need a parameter, but when I call it within a class i need to supply the class name for it to work. For example, MainWindow.class_func2() throws an error
class MainWindow():
def __init__(self):
print("in init")
def claas_func(self):
print ("func1")
def class_func2(self):
outside_func()
def outside_func():
print('outside called')
instance = MainWindow()
MainWindow.class_func2(MainWindow)
You should take a look to #staticmethod
class MainWindow():
def __init__(self):
print("in init")
def claas_func(self):
print ("func1")
#staticmethod
def class_func2():
return outside_func()
def outside_func():
print('outside called')
instance = MainWindow()
>> in init
instance.class_func2()
>> outside called
this #staticmethod (which itself it's something really cool called 'decorator') will make the method itself entirely callable without having pass 'self'.
Hope it helps
Try this instead. You have created an instance of MainWindow(). Now you can access its members with that.
class MainWindow():
def __init__(self):
print("in init")
def claas_func(self):
print ("func1")
def class_func2(self):
outside_func()
def outside_func():
print('outside called')
instance = MainWindow()
instance.class_func2()
Also run this and notice it initializes the MainWindow() class 2x. I DO NOT recommend this second approach. It is redundant and not proper. But just so you can kind of see what it is doing.
class MainWindow():
def __init__(self):
print("in init")
def claas_func(self):
print ("func1")
def class_func2(self):
outside_func()
def outside_func():
print('outside called')
instance = MainWindow()
MainWindow().class_func2()

dynamic method binding in python

I have the following two classes A and B. How do I make the do_someting() method call the overriden method, some_method(), in B. Is this doable in Python?
class A:
#staticmethod
def some_method()
# pass
return
#classmethod
def do_something():
A.some_method()
...
return
class B(A):
#staticmethod
def some_method()
# how does do_something call here?
return
#classmethod
def run()
B.do_something()
return
It's pretty simple, just make sure to fix your colons pass in self and cls:
class A:
#staticmethod
def some_method():
# pass
return
#classmethod
def do_something(cls):
cls.some_method()
return
class B(A):
#staticmethod
def some_method():
print("I did stuff!")
return
#classmethod
def run(cls):
B.do_something()
return
k = B()
k.run()
>>>"I did stuff!"
And if you want to call the old do_something (the one in class A) from class B, just pass in the appropriate class. In class B:
#classmethod
def run(cls):
A.do_something()
return

Calling different parent-class methods with one decorator

So basically my problem seems like this.
class A():
def func(self):
return 3
class B():
def func(self):
return 4
class AA(A):
def func(self):
return super(AA, self).func
class BB(B):
def func(self):
return super(BB, self).func
The func function is doing some work and one of the things it does is getting some attribute(or running method or whatever) from it's parent class.
Since func originally does the same logic at both cases (except that only parent class changes) I'd like to do this with decorators.
Is it possible? if so how to do it? Do I have somehow to pass parent-class as a argument?
I'll be very grateful for answers it's been bothering me for a while now.
There is no need to use super to access data attributes of a parent class.
Neither does a class need a parent in order for access to data attributes to work.
You can use a mixin to do the job:
# A and B stay the same - they still have a c attribute
class A():
c = 3
class B():
c = 4 # I've changed B to make it clear below
#Instead have a mixin which defines func()
class Mixin:
def func(self):
# func has its behaviour here
return self.c
class AA(Mixin, A):
pass
class BB(Mixin, B):
pass
a = AA()
b = BB()
print(a.func())
print(b.func())
Output:
3
4
You could do it with a single class decorator by defining a generic method inside of it that does what you want, and then adding it to the class being decorated. Here's what I mean:
def my_decorator(cls):
def call_super_func(self):
return super(type(self), self).func()
setattr(cls, 'call_super_func', call_super_func)
return cls
class A():
def func(self):
print('in A.func')
return 3
class B():
def func(self):
print('in B.func')
return 4
#my_decorator
class AA(A):
def func(self):
print('in AA.func')
return self.call_super_func()
#my_decorator
class BB(B):
def func(self):
print('in BB.func')
return self.call_super_func()
aa = AA()
aa.func()
bb = BB()
bb.func()
Output:
in AA.func
in A.func
in BB.func
in B.func
Of course you could eliminate the need to do this by just defining baseclass for A and B that has a call_super_func() method in it that they would then both inherit.

python: cleanest way to wrap each method in parent class in a "with"

I have a parent class that has a bunch of class methods:
class Parent():
#classmethod
def methodA(cls):
pass
#classmethod
def methodB(cls):
pass
In my subclass, I would like to wrap a subset of the methods inside a "with". It should achieve this effect:
class Child(Parent):
#classmethod
def methodA(cls):
with db.transaction:
super(Child, cls).methodA()
I have a bunch of methods that follow this pattern and would prefer not to repeat myself. Is there a cleaner way to do this?
It seems you should move the with db.transaction into the base.
Make a method in the base, returning the db.transaction
#staticmethod
def gettransaction(): return db.transaction
then you overload it in the children as/if needed.
In the base you then do
def methodB(cls):
with cls.gettransaction():
bla ...
Here's a complete working example with a dummy transaction
class transact:
def __enter__(a):
print "enter"
def __exit__(a,b,c,d):
print "exit"
class transact2:
def __enter__(a):
print "enter2"
def __exit__(a,b,c,d):
print "exit2"
class Parent():
#staticmethod
def gettrans():
return transact()
def methodA(cl):
with cl.gettrans():
print "A"
class Child(Parent):
pass
#staticmethod
def gettrans():
return transact2()
p=Parent()
p.methodA()
c=Child()
c.methodA()
this results in
enter
A
exit
enter2
A
exit2

Categories