Python's descriptor "__get__" was not called as I expected, reason? - python

I was trying python's descriptor of get, to see if it's called.
I've got the following:
"""This is the help document"""
class c1(object):
"""This is my __doc__"""
def __get__(s,inst,owner):
print "__get__"
def __init__(s):
print "__init__"
s.name='abc'
class d(object):
def __init__(s):
s.c=c1()
d1=d()
d1.c
print d1.c.name
I expect that it will call get function. But it fact the output is
__init__
abc
Why my "get" function was not called by instance owner of "d1"?
Thanks!

Descriptors must be bound to a class, not an instance.
class d(object):
c = c1()

Related

Is `self` actually mandatory for class methods in Python?

I saw a code snippet in Python 3.6.5 that can be replicated with this simplified example below and I do not understand if this is something concerning or not. I am surprised it works honestly...
class Foo:
def bar(numb):
return numb
A1 = bar(1)
print(Foo)
print(Foo.A1)
print(Foo.bar(17))
In all python guides that I have seen, self appears as the first argument for all the purposes we know and love. When it is not, the methods are decorated with a static decorator and all is well. This case works as it is, however. If I were to use the static decorator on bar, I get a TypeError when setting A1:
Traceback (most recent call last):
File "/home/user/dir/understanding_classes.py", line 1, in <module>
class Foo:
File "/home/user/dir/understanding_classes.py", line 7, in Foo
A1 = bar(1)
TypeError: 'staticmethod' object is not callable
Is this something that is OK keeping in the code or is this a potential problem? I hope the question is not too broad, but how and why does this work?
The first parameter of the method will be set to the receiver. We call it self by convention, but self isn't a keyword; any valid parameter name would work just as well.
There's two different ways to invoke a method that are relevant here. Let's say we have a simple Person class with a name and a say_hi method
class Person:
def __init__(self, name):
self.name = name
def say_hi(self):
print(f'Hi my name is {self.name}')
p = Person('J.K.')
If we call the method on p, we'll get a call to say_hi with self=p
p.say_hi() # self=p, prints 'Hi my name is J.K.'
What you're doing in your example is calling the method via the class, and passing that first argument explicitly. The equivalent call here would be
Person.say_hi(p) # explicit self=p, also prints 'Hi my name is J.K.'
In your example you're using a non-static method then calling it through the class, then explicitly passing the first parameter. It happens to work but it doesn't make a lot of sense because you should be able to invoke a non-static method by saying
f = Foo()
f.bar() # numb = f, works, but numb isn't a number it's a Foo
If you want to put a function inside of a class that doesn't have a receiver, that's when you want to use #staticmethod (or, #classmethod more often)
class Person:
def __init__(self, name):
self.name = name
def say_hi(self):
print(f'Hi my name is {self.name}')
#staticmethod
def say_hello():
print('hello')
p = Person('J.K.')
Person.say_hello()
p.say_hello()

how to start or call a function from a different class in python?

hey guys need to know as of how to start a method in a classA from class B
have
classA(object):
def __init__(self):
#this is where the ClassB method'' def multiplyPeople() ''should be called or started.
classB(object):
def multiplyPeople(self):
its giving an error
TypeError: unbound method multiplyPeople() must be called
with classB instance as first argument (got nothing instead)
know this is something basic, but am trying to figure out what exactly is supposed to be done and where am I getting lost.
I have called it as
classA(object):
def__init__(self):
self.PeopleVariable=classB.multiplyPeople()
It depends on how you want the function to work. Do you just want to use the class as a placeholder? Then you can use a so called static method for which you do not need to instantiate an object.
Or you can use a regular method and use it on a created object (notice that there you have access to self)
class A():
def __init__(self):
b = B()
b.non_static()
B.multiplyPeople()
class B():
#staticmethod
def multiplyPeople():
print "this was called"
def non_static(self):
print self, " was called"
if __name__ == "__main__":
a = A()
output:
<__main__.B instance at 0x7f3d2ab5d710> was called
this was called

Method of an object in Python

I was just pulling off a toy example for myself, but it is not working and I cannot make it work. Does anybody know why this is not working and how to make it work:
class A(object):
#def __init__():
#pass
def do1():
print("foo")
def do2():
print("Hello")
Al = A
Al.do1()
TypeError: unbound method do1() must be called with A instance as first argument (got nothing instead)
In your code variable A1 it's reference to your class not instance, create instance of your class
Al = A()
and run your method
Al.do1()
You need to call your class to crate a correct instance and pass the self keyword to enclosing function to provides a handle back to the instance to be processed :
class A(object):
#def __init__():
#pass
def do1(self):
print("foo")
def do2():
print("Hello")
Al = A()
Al.do1()
Note that without passing the self to your function after calling it you will get a TypeError.
TypeError: do1() takes 0 positional arguments but 1 was given
Or as #Padraic Cunningham mentioned in comment you can use staticmethod as a decorator to wrap your function which makes python doesn't pass the first default argument (self) to it.
class A(object):
#def __init__():
#pass
#staticmethod
def do1():
print("foo")
def do2():
print("Hello")
Al = A()
Al.do1()

Better solution to access class that owns the method from a method decorator

Recently, I faced a problem which was similar to this question:
Accessing the class that owns a decorated method from the decorator
My rep was not high enough to comment there, so I am starting a new question to address some improvements to the answer to that problem.
This is what I needed:
def original_decorator(func):
# need to access class here
# for eg, to append the func itself to class variable "a", to register func
# or say, append func's default arg values to class variable "a"
return func
class A(object):
a=[]
#classmethod
#original_decorator
def some_method(self,a=5):
''' hello'''
print "Calling some_method"
#original_decorator
def some_method_2(self):
''' hello again'''
print "Calling some_method_2"
The solution would need to work both with class methods and instance methods, the method returned from the decorator should work and behave just the same way if it was undecorated i.e. method signature should be preserved.
The accepted answer for that question returned a Class from the decorator and the metaclass identified that specific Class, and did the "class-accessing" operations.
The answer did mention itself as a rough solution, but clearly it had a few caveats :
Decorator returned a class and it was not callable. Obviously, it can be made callable easily, but the returned value is still a class - it just behaves the same way while calling, but its properties and behaviors would be different. Essentially, it would not work the same way as the undecorated method.
It forced the decorator to return a custom-type class and all the "class-accessing" code was put inside the metaclass directly. It is simply not nice, writing the decorator should not enforce touching the metaclass directly.
I have tried to come up with a better solution, documented in the answer.
Here is the solution.
It uses a decorator (which would work on "class-accessing" decorators) and a metaclass, which would fulfill all my requirements and address the problems of that answer. Probably the best advantage is that the "class-accessing" decorators can just access the class, without even touching the metaclass.
# Using metaclass and decorator to allow class access during class creation time
# No method defined within the class should have "_process_meta" as arg
# Potential problems: Using closures, function.func_globals is read-only
from functools import partial
import inspect
class meta(type):
def __new__(cls, name, base, clsdict):
temp_cls = type.__new__(cls, name, base, clsdict)
methods = inspect.getmembers(temp_cls, inspect.ismethod)
for (method_name, method_obj) in methods:
tmp_spec = inspect.getargspec(method_obj)
if "__process_meta" in tmp_spec.args:
what_to_do, main_func = tmp_spec.defaults[:-1]
f = method_obj.im_func
f.func_code, f.func_defaults, f.func_dict, f.func_doc, f.func_name = main_func.func_code, main_func.func_defaults, main_func.func_dict, main_func.func_doc, main_func.func_name
mod_func = what_to_do(temp_cls, f)
f.func_code, f.func_defaults, f.func_dict, f.func_doc, f.func_name = mod_func.func_code, mod_func.func_defaults, mod_func.func_dict, mod_func.func_doc, mod_func.func_name
return temp_cls
def do_it(what_to_do, main_func=None):
if main_func is None:
return partial(do_it, what_to_do)
def whatever(what_to_do=what_to_do, main_func=main_func, __process_meta=True):
pass
return whatever
def original_classmethod_decorator(cls, func):
# cls => class of the method
# appends default arg values to class variable "a"
func_defaults = inspect.getargspec(func).defaults
cls.a.append(func_defaults)
func.__doc__ = "This is a class method"
print "Calling original classmethod decorator"
return func
def original_method_decorator(cls, func):
func_defaults = inspect.getargspec(func).defaults
cls.a.append(func_defaults)
func.__doc__ = "This is a instance method" # Can change func properties
print "Calling original method decorator"
return func
class A(object):
__metaclass__ = meta
a = []
#classmethod
#do_it(original_classmethod_decorator)
def some_method(cls, x=1):
''' hello'''
print "Calling original class method"
#do_it(original_method_decorator)
def some_method_2(self, y=2):
''' hello again'''
print "Calling original method"
# signature preserved
print(inspect.getargspec(A.some_method))
print(inspect.getargspec(A.some_method_2))
Open to suggestions on whether this approach has any ceveats.

Python - Exists a function that is called when an object does not implement a function?

In Smalltalk there is a message DoesNotUnderstand that is called when an object does not understand a message (this is, when the object does not have the message sent implemented).
So, I like to know if in python there is a function that does the same thing.
In this example:
class MyObject:
def __init__(self):
print "MyObject created"
anObject = MyObject() # prints: MyObject created
anObject.DoSomething() # raise an Exception
So, can I add a method to MyObject so I can know when DoSomething is intented to be called?
PS: Sorry for my poor English.
Here is a proposition for what you want to do:
class callee:
def __init__(self, name):
self.name = name
def __call__(self):
print self.name, "has been called"
class A:
def __getattr__(self, attr):
return callee(attr)
a = A()
a.DoSomething()
>>> DoSomething has been called
You are looking for the __getattr__ method. Have a look here.
If you want "total control" of a class, look at the __getattribute__ special method then (here).
Have you looked at object.__getattr__(self, name), or object.__getattribute__(self, name) for new-style classes? (see Special method names, Python language reference)
I don't know why luc had the two separate classes. You can do it all with one class, if you use a closure. Like so:
class A(object):
__ignored_attributes__ = set(["__str__"])
def __getattr__(self, name):
if __name__ in self.__ignored_attributes__:
return None
def fn():
print name, "has been called with self =", self
return fn
a = A()
a.DoSomething()
I added the bit about __ignored_attributes__ because Python was looking up __str__ in the class and that got a little messy.

Categories