Let say I have
class A(object):
def m1(self):
B().m2()
class B(object):
def m2(self):
#return object of caller instance
#let say 'a' is instance object this method was called from
return a
a = A().m1()
You can pass the caller instance, and make it a parameter of the called function itself. Something like -
class A(object):
def m1(self):
B().m2(self)
class B(object):
def m2(self, obj):
#return object of caller instance
#let say 'a' is instance object this method was called from
return obj
a = A().m1()
Related
class A:
def func(self):
print('This was in A')
class B(A):
def text(self):
print('This is in B')
print(B.func.__qualname__)
The output of this would be A.func but I'd like it to be B.func
It would be like functools.wraps but for class functions.
I'm not sure how exactly you'll be using this in logging, it would help if you could elaborate on your question. Here I assume what you want is a function (named print_func), that when passed with an instance method, prints the method name and class name of the actual instance.
In this case, you can just separately print the instance class name and the method name, for example:
class A:
def func(self):
print('This was in A')
class B(A):
def text(self):
print('This is in B')
def print_func(f):
print(f.__self__.__class__.__qualname__, ".", f.__name__)
b = B()
print_func(b.func) # B . func
The __self__ attribute of a bound instance method gives the instance that the method is bound to (in this case, b), and __class__ of an instance gives the class of the instance.
You can also extend the print_func method by checking whether f is a bound instance method, and add additional routines for normal functions, static methods, and class methods. An example would be:
import inspect
def print_func(f):
if inspect.ismethod(f):
# Could be instance method or class method.
self = f.__self__
if inspect.isclass(self):
print("classmethod", self.__qualname__ + "." + f.__name__)
else:
print(self.__class__.__qualname__ + "." + f.__name__)
else:
# The method is either an unbound instance method, a static method,
# or a normal function. Either case, it is not bound to an instance,
# so `__qualname__` should suffice.
# It would be non-trivial to print the actual class from which we
# accessed this function. See examples marked with asterisks (*) below.
print(f.__qualname__)
To see it in action:
class A:
def method(self): pass
#classmethod
def classmethod(cls): pass
#staticmethod
def staticmethod(): pass
class B(A):
pass
def function(): pass
a = A()
b = B()
print_func(A.method) # A.method
print_func(B.method) # A.method *
print_func(a.method) # A.method
print_func(b.method) # B.method
print_func(A.classmethod) # classmethod A.classmethod
print_func(B.classmethod) # classmethod B.classmethod
print_func(a.classmethod) # classmethod A.classmethod
print_func(b.classmethod) # classmethod B.classmethod
print_func(A.staticmethod) # A.staticmethod
print_func(B.staticmethod) # A.staticmethod *
print_func(function) # function
Seems that not so good solution, but it can help you:
class A:
def func(self):
print('This was in A')
class B(A):
def text(self):
print('This is in B')
def func(self):
return super().func()
print(B.func.__qualname__)
How to return a list from the class level using properties? When call instance a class it's all ok, but when it calls the attribute class, it gets the property object
below sample code:
class zoo:
__count_animals=0
__listAnimals=[]
def __init__(self,typee,name,age):
self.typee=typee
self.name=name
self.age=age
self.__listAnimals.append(self)
zoo.__count_animals+=1
#property
def count_animals(self):
return self.__count_animals
#count_animals.setter
def count_animals(self,newvalue):
newvalue=zoo.__ilosc_zwierzat
self.__count_animals=newvalue
#property
def listAnimals(self):
return self.__listAnimals
#listAnimals.setter
def listAnimals(self,newobj):
newobj=zoo.__listAnimals
self.__listAnimals=newobj
zw1=zoo("Tiger","NoName",23)
print(zw1.listAnimals) # result it's ok ->[<__main__.zoo object at 0x006A23D0>, <__main__.zoo object at 0x006A2410>]
but
print(zoo.listAnimals) # result <property object at 0x002A1DB0>
This works as expected. Because you are calling the property object on class instead on instance. Class does not hold the same data as class instances.
The way you expect it to happen is that __count_animals and __listAnimals are class properties instead of instance properties.
So I slightly modified your code to work with classproperties instead of instance properties.
Above I define classproperty decorator:
class classproperty(object):
def __init__(self, f):
self.f = f
def __get__(self, obj, owner):
return self.f(owner)
Then your class zoo
class zoo:
__count_animals=0
__listAnimals=[]
def __init__(self,typee,name,age):
self.typee=typee
self.name=name
self.age=age
zoo.__listAnimals.append(self)
zoo.__count_animals+=1
#classproperty
def count_animals(self):
return self.__count_animals
#classproperty
def listAnimals(cls):
return cls.__listAnimals
zw1=zoo("Tiger","NoName",23)
print(zoo.listAnimals) # result [<__main__.zoo object at 0x10699c410>]
Works like a charm!
You are calling the class property, you need first to instance that class in to an object and then get the property of the object.
Is there a way in Python to define a method that is both a class method and an instance method, such that both cls and self are receivers. In particular, I am looking to make a method that (1) knows which class it was called on when called on the class (Foo.method(value)) and (2) knows which instance it was called on when called on an instance (foo.method()).
For example, I would envision something working like this:
class Foo:
def __str__(self): return 'Foo()'
#classinstancemethod
def method(cls, self):
print(cls, self)
class Bar(Foo):
def __str__(self): return 'Bar()'
Foo().method() # <class '__main__.Foo'> Foo()
Bar().method() # <class '__main__.Bar'> Bar()
Foo.method(Foo()) # <class '__main__.Foo'> Foo()
Foo.method(Bar()) # <class '__main__.Foo'> Bar()
Bar.method(Foo()) # <class '__main__.Bar'> Foo()
Note that I am aware that undecorated methods can be called like Foo.foo(value), but this is not what I want because it doesn't get the cls variable. And without the cls variable, the method has no idea which class it was just called on. It may have been called as Bar.method(value), and there would be now way to know that if value was an instance of Foo. An undecorated method is more like both a static method and an instance method, not both a class method and an instance method.
This can be solved by implementing classinstancemethod as a custom descriptor.
In a nutshell, the descriptor must define a __get__ method that will be called when it's accessed as an attribute (like Foo.method or Foo().method). This method will be passed the instance and the class as arguments and returns a bound method (i.e. it returns a method with the cls and self arguments baked in). When this bound method is called, it forwards the baked-in cls and self parameters to the actual method.
class classinstancemethod:
def __init__(self, method, instance=None, owner=None):
self.method = method
self.instance = instance
self.owner = owner
def __get__(self, instance, owner=None):
return type(self)(self.method, instance, owner)
def __call__(self, *args, **kwargs):
instance = self.instance
if instance is None:
if not args:
raise TypeError('missing required parameter "self"')
instance, args = args[0], args[1:]
cls = self.owner
return self.method(cls, instance, *args, **kwargs)
Results:
class Foo:
def __repr__(self): return 'Foo()'
#classinstancemethod
def method(cls, self):
print((cls, self))
class Bar(Foo):
def __repr__(self): return 'Bar()'
Foo().method() # (<class '__main__.Foo'>, 'Foo()')
Bar().method() # (<class '__main__.Bar'>, 'Bar()')
Foo.method(Foo()) # (<class '__main__.Foo'>, 'Foo()')
Foo.method(Bar()) # (<class '__main__.Foo'>, 'Bar()')
Bar.method(Foo()) # (<class '__main__.Bar'>, 'Foo()')
You don't need a decorator for this. This is how methods already work; the instance is passed as first argument – implicitly when method is called from instance and explicitly from the class – with the instance available, you can retrieve the class by calling type on the instance:
class Foo(object):
def __repr__(self): return 'Foo()'
def method(self):
print((type(self), self))
class Bar(Foo):
def __repr__(self): return 'Bar()'
On another note, in the __str__ (or __repr__) special methods, you should return a string, not print.
I have used __repr__ since __str__ is not called for printing the instance when inside a container object (tuple here).
Update:
Considering the issues with class/instance printing in the above approach, you can use a descriptor instead to properly manage correct class and instance selection within the method:
class classinstancemethod():
def __get__(self, obj, cls):
def method(inst=None):
print(cls, inst if inst else obj)
return method
class Foo(object):
method = classinstancemethod()
def __str__(self): return 'Foo()'
class Bar(Foo):
def __str__(self): return 'Bar()'
Lets say I have this class:
class Test(object):
def __init__(self, a):
self.a = a
def test(self, b):
if isinstance(self, Test):
return self.a + b
else:
return self + b
This would ideally in my world do this:
>>> Test.test(1,2)
3
>>> Test(1).test(2)
3
Now this doesn't work because you get this error:
TypeError: unbound method test() must be called with Test instance as first argument (got int instance instead)
In python3 this works fine, and I have the sneaking suspicion this is possible with a decorator in python2 but my python foo isn't strong enough to get that to work.
Plot Twist: So what happens when I need something on self when it's not called statically.
If you want something that will actually receive self if called on an instance, but can also be called on the class, writing your own descriptor type may be advisable:
import types
class ClassOrInstanceMethod(object):
def __init__(self, wrapped):
self.wrapped = wrapped
def __get__(self, instance, owner):
if instance is None:
instance = owner
return self.wrapped.__get__(instance, owner)
class demo(object):
#ClassOrInstanceMethod
def foo(self):
# self will be the class if this is called on the class
print(self)
Demo.
For the original version of your question, you could just write it like any other static method, with #staticmethod. Calling a static method on an instance works the same as calling it on the class:
class Test(object):
#staticmethod
def test(a, b):
return a + b
Demo.
I got an unexpected closure when creating a nested class. I suspect that this is something related to metaclasses, super, or both. It is definitely related to how closures get created. I am using python2.7.
Here are five simplified examples that demonstrate the same problem that I am seeing (they all build off the first):
EXAMPLE 1:
class Metaclass(type):
def __init__(self, name, bases, dict):
self.CONST = 5
class Base(object):
__metaclass__=Metaclass
def __init__(self):
"Set things up."
class Subclass(Base):
def __init__(self, name):
super(Subclass, self).__init__(self)
self.name = name
def other(self, something): pass
class Test(object):
def setup(self):
class Subclass(Base):
def __init__(self, name):
super(Subclass, self).__init__(self)
self.name = name
def other(self, something): pass
self.subclass = Subclass
class Subclass2(Base):
def __init__(self, name):
super(Subclass, self).__init__(self)
self.subclass2 = Subclass2
"0x%x" % id(Metaclass)
# '0x8257f74'
"0x%x" % id(Base)
# '0x825814c'
t=Test()
t.setup()
"0x%x" % id(t.subclass)
# '0x8258e8c'
"0x%x" % id(t.subclass2)
# '0x825907c'
t.subclass.__init__.__func__.__closure__
# (<cell at 0xb7d33d4c: Metaclass object at 0x8258e8c>,)
t.subclass.other.__func__.__closure__
# None
t.subclass2.__init__.__func__.__closure__
# (<cell at 0xb7d33d4c: Metaclass object at 0x8258e8c>,)
Subclass.__init__.__func__.__closure__
# None
EXAMPLE 2:
class Test2(object):
def setup(self):
class Subclass(Base):
def __init__(self, name):
self.name = name
def other(self, something): pass
self.subclass = Subclass
t2=Test2()
t2.setup()
t2.subclass.__init__.__func__.__closure__
# None
EXAMPLE 3:
class Test3(object):
def setup(self):
class Other(object):
def __init__(self):
super(Other, self).__init__()
self.other = Other
class Other2(object):
def __init__(self): pass
self.other2 = Other2
t3=Test3()
t3.setup()
"0x%x" % id(t3.other)
# '0x8259734'
t3.other.__init__.__func__.__closure__
# (<cell at 0xb7d33e54: type object at 0x8259734>,)
t3.other2.__init__.__func__.__closure__
# None
EXAMPLE 4:
class Metaclass2(type): pass
class Base2(object):
__metaclass__=Metaclass2
def __init__(self):
"Set things up."
class Base3(object):
__metaclass__=Metaclass2
class Test4(object):
def setup(self):
class Subclass2(Base2):
def __init__(self, name):
super(Subclass2, self).__init__(self)
self.subclass2 = Subclass2
class Subclass3(Base3):
def __init__(self, name):
super(Subclass3, self).__init__(self)
self.subclass3 = Subclass3
class Subclass4(Base3):
def __init__(self, name):
super(Subclass4, self).__init__(self)
self.subclass4 = Subclass4
"0x%x" % id(Metaclass2)
# '0x8259d9c'
"0x%x" % id(Base2)
# '0x825ac9c'
"0x%x" % id(Base3)
# '0x825affc'
t4=Test4()
t4.setup()
"0x%x" % id(t4.subclass2)
# '0x825b964'
"0x%x" % id(t4.subclass3)
# '0x825bcac'
"0x%x" % id(t4.subclass4)
# '0x825bff4'
t4.subclass2.__init__.__func__.__closure__
# (<cell at 0xb7d33d04: Metaclass2 object at 0x825b964>,)
t4.subclass3.__init__.__func__.__closure__
# (<cell at 0xb7d33e9c: Metaclass2 object at 0x825bcac>,)
t4.subclass4.__init__.__func__.__closure__
# (<cell at 0xb7d33ddc: Metaclass2 object at 0x825bff4>,)
EXAMPLE 5:
class Test5(object):
def setup(self):
class Subclass(Base):
def __init__(self, name):
Base.__init__(self)
self.subclass = Subclass
t5=Test5()
t5.setup()
"0x%x" % id(t5.subclass)
# '0x8260374'
t5.subclass.__init__.__func__.__closure__
# None
Here is what I understand (referencing examples):
Metaclasses are inherited, so Subclass gets Base’s metaclass.
Only __init__ is affected, Subclass.other method is not (#1).
Removing Subclass.other does not make a difference (#1).
Removing self.name=name from Subclass.__init__ does not make a difference (#1).
The object in the closure cell is not a function.
The object is not Metaclass or Base, but some object of type Metaclass, just like Base is (#1).
The object is actually an object of the type of the nested Subclass (#1).
The closure cells for t1.subclass.__init__ and t1.subclass2.__init__ are the same, even though they are from two different classes (#1).
When I do not nest the creation of Subclass (#1) then there is no closure created.
When I do not call super(...).__init__ in Subclass.init__ no closure is created (#2).
If I assign no __metaclass__ and inherit from object then the same behavior shows up (#3).
The object in the closure cell for t3.other.__init__ is t3.other (#3).
The same behavior happens if the metaclass has no __init__ (#4).
The same behavior happens if the Base has no __init__ (#4).
The closure cells for the three subclasses in example 4 are all different and each matches the corresponding class (#4).
When super(...).__init__ is replaced with Base.__init__(self), the closure disappears (#5).
Here is what I do not understand:
Why does a closure get set for __init__?
Why doesn't the closure get set for other?
Why is the object in the closure cell set to the class to which __init__ belongs?
Why does this only happen when super(...).__init__ is called?
Why doesn't this happen when Base.__init__(self) is called?
Does this actually have anything at all to do with using metaclasses (probably, since the default metaclass is type)?
Thanks for the help!
-eric
(Update) Here is something that I found then (based on Jason's insight):
def something1():
print "0x%x" % id(something1)
def something2():
def something3():
print "0x%x" % id(something1)
print "0x%x" % id(something2)
print "0x%x" % id(something3)
return something3
return something2
something1.__closure__
# None
something1().__closure__
# 0xb7d4056c
# (<cell at 0xb7d33eb4: function object at 0xb7d40df4>,)
something1()().__closure__
# 0xb7d4056c
# (<cell at 0xb7d33fec: function object at 0xb7d40e64>, <cell at 0xb7d33efc: function object at 0xb7d40e2c>)
something1()()()
# 0xb7d4056c
# 0xb7d4056c
# 0xb7d40e9c
# 0xb7d40ed4
First, a function's name is in scope within its own body. Second, functions get closures for the functions in which they are defined if they reference those functions.
I hadn't realized that the function name was in scope like that. The same goes for classes. When a class is defined within a function's scope, any references to that class name inside the class's methods cause the class to bound in a closure on that method's function, like so:
def test():
class Test(object):
def something(self):
print Test
return Test
test()
# <class '__main__.Test'>
test().something.__func__.__closure__
# (<cell at 0xb7d33c2c: type object at 0x825e304>,)
However, since closures cannot be created on non-functions the following fails:
def test():
class Test(object):
SELF=Test
def something(self):
print Test
return Test
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# File "<stdin>", line 2, in test
# File "<stdin>", line 3, in Test
# NameError: free variable 'Test' referenced before assignment in enclosing scope
Good stuff!
Why does a closure get set for __init__?
It refers to a local variable (namely Subclass) in the enclosing function (namely setup).
Why doesn't the closure get set for other?
Because it doesn't refer to any local variables (or parameters) in any enclosing functions.
Why is the object in the closure cell set to the class to which __init__ belongs?
That is the value of the enclosing variable being referred to.
Why does this only happen when super(...).__init__ is called?
Why doesn't this happen when Base.__init__(self) is called?
Because Base is not a local variable in any enclosing function.
Does this actually have anything at all to do with using metaclasses?
No.