I've got a class, where a method should only run once. Of course, it could easily be done with artificial has_executed = True/False flag, but why use it, if you can just delete the method itself? python's a duck-typed language, everything is a reference, bla-bla-bla, what can go wrong?
At least it was the thought. I couldn't actually do it:
class A:
def b(self):
print("empty")
self.__delattr__('b')
a = A()
a.b()
raises AttributeError: b. However, executing self.__getattribute__('b') returns <bound method A.b of <__main__.A object at 0x000001CDC6742FD0>>, which sounds stupid to me: why is a method any different from an attribute, since everything in python is just a reference to an object? And why can I __getattribute__, but not __delattr__?
The same goes to redefinition. I can easily set any attribute, but methods are a no-no?
class A:
def b(self):
print("first")
self.__setattr__('b', lambda self: print(f"second"))
a = A()
a.b()
a.b()
results into TypeError: <lambda>() missing 1 required positional argument: 'self'. Which, of course, means, that now python isn't using dot-notation as intended. Of course, we could ditch the self attribute in the lambda altogether, considering we've got the reference to it already in b. But isn't it incorrect by design?
The further I'm trying to take python to the limit, the more frustrated I become. Some imposed limitations (or seemingly imposed?) seem so unnatural, considering the way the language is marketed. Shouldn't it allow this? Why doesn't it work?
UPD
Ok, consider this:
class A:
def __init__(self):
self.variable = 1
def b(self):
print("old")
self.variable += 1
def new_b():
print("new")
self.variable += 15
self.__setattr__('b', new_b)
It will work and do what we want: none of other objects will have their A.b method redefined once one object kind of overlays its b definition. (overlays, since everyone so far says that you cannot redefine a method for an object, but instead only kind of hide it from the caller behind another attribute with the same name, as far as I understand).
Is this good?
It doesn't work because b isn't an attribute belonging to the instance, it belongs to the class. So you can't delete it on the instance because it isn't there to be deleted.
>>> a = A()
>>> list(a.__dict__)
[]
>>> list(A.__dict__)
['__module__', 'b', '__dict__', '__weakref__', '__doc__']
When a.b is evaluated, Python will see that a has no instance attribute named b and fall back to the class. (It's a little more complicated because when falling back to the class, it will not simply return the method itself, but a version of the method which is bound to the instance a.)
Since you don't want to delete the method on the class, the way to go is to replace the method on the instance. I don't know why you tried to do this with __setattr__ - there is no need for that, simply assign self.b = ... as normal. The reason your attempt failed is because your lambda requires a positional parameter named self, but this parameter will not be automatically bound to the instance when you look it up, because it is an instance attribute, not a class attribute.
class A:
def b(self):
print('first')
self.b = lambda: print('second')
Usage:
>>> a = A()
>>> a.b()
first
>>> a.b()
second
Well in python you have 2 types of attributes
A class attribute is a variable that belongs to a certain class, and not a particular object. Every instance of this class shares the same variable. These attributes are usually defined outside the init constructor
An instance/object attribute is a variable that belongs to one (and only one) object. Every instance of a class points to its own attributes variables. These attributes are defined within the init constructor.
In case of a class attribute its part of the class descriptor, so you cannot delete it from the object attributes like self.__deleteattr__ or add new one with __setattr__ as it alters the class descriptor and reflects on all objects. Such an operation can have devastating effects.
Its very similar to a class variable as well. You can however change the behavior with overriding or reassigning like below
class A:
def b(self):
print("empty")
A.b = lambda self: print(f"second")
a = A()
a.b()
a.b()
Related
my question may sound a bit weird. In JS we can put an object on another one, how does it work in Python? what is the name of this functionality?
Example:
class A:
def __init__(self):
print('I am A')
class B:
def __init__(self):
print('I am B')
def i_am_a_function(x):
print('I am function')
print(x)
# What if I create a method using dot:
A.holder_for_b = B
# OR:
A.some_method = i_am_a_function
########
print(A.holder_for_b)
print(A.some_method('foo'))
result:
<class '__main__.B'>
I am function
foo
None
and as a final question, what is that "None" ?
I think you mean:
class A:
def __init__(self):
print('I am A')
class B:
def __init__(self):
print('I am B')
def i_am_a_function(x):
print('I am function')
print(x)
a = A()
b = B()
# What if I create a method using dot:
a.holder_for_b = B
# OR:
a.some_method = i_am_a_function
########
print(a.holder_for_b)
print(a.some_method('foo'))
## outputs:
I am A
I am B
<class '__main__.B'>
I am function
foo
None
So it seems that you can assign a function to an object. This is called in Python "monkey patching".
But the disadvantage of this is - I think:
It applies only to the object a - so you can't inherit it to another object
(different than in javascript I guess - prototype).
You can't interact with any other property or method in the class,
because you don't have self (in js this) available in that monkey-patched method.
(If I am wrong, please tell me.)
And it is bad style, because you should have in the class definition everything what you need. It would be hard to understand for anyone who wants to maintain the code.
Also the a.holder_for_b = B is unnecessary.
For what you would need a.holder_for_b? You can't anyway not inherit such a monkey-patched method to another object in Python.
Python's class definitions are lexical.
None
The None is the return value of the function call.
x = a.some_method('foo')
## I am function
## foo
x
## Nothing returned
x is None
## returns: True
print(x)
## None
As you can see: x returns nothing.
The None would not be visible if you would not have used print() around the call a.some_method('foo').
So the function is called - which prints I am a function and foo.
But the return value (None) gets returned from this call - and the print() prints it.
Putting an object to another
Do you mean "attaching"? This is very well possible in Python - by monkey patching.
a = A()
a.b = B()
Now, b is an attribut/property of the object a, which holds the object generated by B(). You could also just assign any already generated object to a in a similar way.
But this applies only to a. And in Python, you cannot generate another object based on a. So it is a little bit pointless in my view.
Perhaps more pythonic ways would be:
# everytime you generate an instance of the A class, generate an instance of B
# and attache it to newly generated instance of the A class as `b`:
class A:
def __init__(self):
print('I am A')
self.b = B()
# generate an instance of A, but attach as `b` property an existing object:
class A:
def __init__(self, obj):
print('I am A')
self.b = obj
b = B()
# ...
a = A(b)
# a.b is then identical to the generated `b` - it is a reference to it.
# So everything to do to it will be done to `b` too!
# This can be very confusing and create bugs.
a.b.my_new_property = 1
a.b.my_new_property ## 1
b.my_new_property ## 1
But I think your problem is that you are trying to apply JavaScript's prototypical OOP system habits to Python. In Python, you should better define everything in your class definitions, give other objects or classes as arguments to the constructor methods (__init__ or __new__).
And if you want to modify class definitions in a re-usable manner, probably use decorators or decorator classes. Or design patterns.
A class defines a namespace. A def creates a function object and assigns it to a variable in the active namespace. If that def is in the class namespace (one indentation in from the class definition), the variable is assigned to the class namespace. In your example, both __init__ functions are assigned to variables called "__init__" in the classes. i_am_a_function is not in a class namespace so it is assigned to the module ("global") namespace.
Normally, accessing a variable in a class namespace is just a name lookup like any other variable.
print(A.holder_for_b)
simply looked up the object in A.holder_for_b, which is a class object. You could add
print(A.holder_for_b())
and get an instance of that class. Similarly A.some_method is just looking up the variable on A. When you call it, you are just calling a function. You saw the print in the function itself and its None return value.
But python does something different if you reference a variable off of a class instance object (as opposed to the class object itself). If you try calling a variable (and it is a function object), python will convert that function object into a method and will automatically add a reference to the the instance as a so-called "self" object.
a = A()
print(a)
print(a.some_method())
prints
I am A
<__main__.A object at 0x7fb6c0ab61c0>
I am function
<__main__.A object at 0x7fb6c0ab61c0>
Here, since you call a variable of an instance object, its first parameter that you called "x" is now the instance object (the "self" parameter). Python didn't really care what you called that variable, its just the first in the parameter list.
I am writing a framework, and I want my base class to use different functions for renaming in the child classes. I figured the best way would be to use a class attribute, like in case of A, but I got TypeErrors when running it like in rename_columns(). However it worked with implementation like B
import pandas as pd
class A:
my_func_mask = str.lower
foo = 'bar'
def rename_columns(self, data):
return data.rename(columns=self.my_func_mask)
class B(A):
def rename_columns(self, data):
return data.rename(columns=self.__class__.my_func_mask)
So I experimented with the above a bit, and I get the following:
a = A()
a.foo # Works fine, gives back 'bar'
a.__class__.my_func_mask # Works as expected `a.__class__.my_func_mask is str.lower` is true
a.my_func_mask # throws TypeError: descriptor 'lower' for 'str' objects doesn't apply to 'A' object
My questions would be why can I use regular typed (int, str, etc.) values as class attributes and access them on the instance as well, while I cannot do that for functions?
What happens during the attribute lookup in these cases? What is the difference in the attribute resolution process?
Actually both foo and my_func_mask is in __class__.__dict__ so I am a bit puzzled. Thanks for the clarifications!
You are storing an unbound built-in method on your class, meaning it is a descriptor object. When you then try to access that on self, descriptor binding applies but the __get__ method called to complete the binding tells you that it can't be bound to your custom class instances, because the method would only work on str instances. That's a strict limitation of most methods of built-in types.
You need to store it in a different manner; putting it inside another container, such as a list or dictionary, would avoid binding. Or you could wrap it in a staticmethod descriptor to have it be bound and return the original. Another option is to not store this as a class attribute, and simply create an instance attribute in __init__.
But in this case, I'd not store str.lower as an attribute value, at all. I'd store None and fall back to str.lower when you still encounter None:
return data.rename(columns=self.my_func_mask or str.lower)
Setting my_func_mask to None is a better indicator that a default is going to be used, clearly distinguishable from explicitly setting str.lower as the mask.
You need to declare staticmethod.
class A:
my_func_mask = staticmethod(str.lower)
foo = 'bar'
>>> A().my_func_mask is str.lower
>>> True
Everything that is placed in the class definition is bound to the class, but you can't bind a built-in to your own class.
Essentially, all code that you place in a class is executed when the class is created. All items in locals() are then bound to your class at the end of the class. That's why this also works to bind a method to your class:
def abc(self):
print('{} from outside the class'.format(self))
class A:
f1 = abc
f2 = lambda self: print('{} from lambda'.format(self))
def f3(self):
print('{} from method'.format(self))
To not have the function bound to your class, you have to place it in the __init__ method of your class:
class A:
def __init__(self):
self.my_func_mask = str.lower
I was actually going through descriptors python docs and came across this example
>>> class D(object):
def f(self, x):
return x
>>> d = D()
>>> D.__dict__['f'] # Stored internally as a function
<function f at 0x00C45070>
>>> id(D.__dict__['f']) # Memory location
49294384
>>> D.f # Get from a class becomes an unbound method
<unbound method D.f>
>>> id(D.f )
48549440
>>> d.f # Get from an instance becomes a bound method
<bound method D.f of <__main__.D object at 0x00B18C90>>
>>> id(d.f)
48549440
So from the above code, I understood that python stores the function definition/declaration of a class as a separate object internally inside class __dict__ variable, when we access directly using __dict__ variable it has memory location as 49294384
But why does it is showing as different function/method object with different memory location 48549440 when accessed through Class or Object? like D.f and d.f
was it not supposed to refer to the same object when we access using the __dict__ variable?. If so why?
D.f is a function taking one argument (self)
x = D.f
x(d)
d.f is a "bound method", i.e. a function where the self argument has already been filled in. You can say
x = d.f
x()
Therefor it cannot be the same thing as D.f, and has to be on a different location.
xtofi explained the difference between descriptor objects (unbound) and bound methods.
I think the missing part is that bound methods are not kept in memory, and they are actually created every time you access them. (You may get the same memory location, but it's not the same object).
Why?
Because on every call on a descriptor may result in a different behavior. Here is an example to explain this idea.
class A(object):
i = 'a'
#property
def name(self):
if A.i == 'a':
return self.fa()
else:
return self.fb()
def fa(self):
print 'one function'
def fb(self):
print 'another function'
Calling the function name on an instance of A results in different function calls.
I'm making a program in python in which specific instances of an object must be decorated with new functions built at runtime.
I've seen very simple examples of adding functions to objects through MethodType:
import types
def foo():
print("foo")
class A:
bar = "bar"
a = A()
a.foo = types.MethodType(foo, a)
But none of the examples I've seen show how a function added in this manner can reference to the new owner's attributes. As far as I know, even though this binds the foo() function to the instance a, foo() must still be a pure function, and cannot contain references to anything local.
In my case, I need functions to change attributes of the object they are added to. Here are two examples of the kind of thing I need to be able to do:
class A:
foo = "foo"
def printme():
print(foo)
def nofoo():
foo = "bar"
def printBar():
if foo != "foo"
self.printme()
I would then need a way to add a copy of a nofoo() or printBar() to an A object in such a way that they can access the object attributes named foo and the function named printme() correctly.
So, is this possible? Is there a way to do this kind of programming in vanilla Python? or at least Is there a programming pattern that achieves this kind of behavior?
P.S.: In my system, I also add attributes dynamically to objects. Your first thought then might be "How can I ever be sure that the object I'm adding the nofoo() function to actually has an attribute named foo?", but I also have a fairly robust tag system that makes sure that I never try to add a nofoo() function to an object that hasn't a foo variable. The reason I mention this is that solutions that look at the class definition aren't very useful to me.
As said in the comments, your function actually must take at least one parameter: self, the instance the method is being called on. The self parameter can be used as it would be used in a normal instance method. Here is an example:
>>> from types import MethodType
>>>
>>> class Class:
def method(self):
print('method run')
>>> cls = Class()
>>>
>>> def func(self): # must accept one argument, `self`
self.method()
>>> cls.func = MethodType(func, cls)
>>> cls.func()
method run
>>>
Without your function accepting self, an exception would be raised:
>>> def func():
self.method()
>>> cls.func = MethodType(func, cls)
>>> cls.func()
Traceback (most recent call last):
File "<pyshell#21>", line 1, in <module>
cls.func()
TypeError: func() takes 0 positional arguments but 1 was given
>>>
class A:
def __init__(self):
self.foo = "foo"
def printme(self):
print(self.foo)
def nofoo(self):
self.foo = "bar"
a.nofoo = types.MethodType(nofoo, a)
a.nofoo()
a.printme()
prints
bar
It's not entirely clear what you're trying to do, and I'm worried that whatever it is may be a bad idea. However, I can explain how to do what you're asking, even if it isn't what you want, or should want. I'll point out that it's very uncommon to want to do the second version below, and even rarer to want to do the third version, but Python does allow them both, because "even rarer than very uncommon" still isn't "never". And, in the same spirit…
The short answer is "yes". A dynamically-added method can access the owner object exactly the same way a normal method can.
First, here's a normal, non-dynamic method:
class C:
def meth(self):
return self.x
c = C()
c.x = 3
c.meth()
Obviously, with a normal method like this, when you call c.meth(), the c ends up as the value of the self parameter, so self.x is c.x, which is 3.
Now, here's how you dynamically add a method to a class:
class C:
pass
c = C()
c.x = 3
def meth(self):
print(self.x)
C.meth = meth
c.meth()
This is actually doing exactly the same thing. (Well, we've left another name for the same function object sitting around in globals, but that's the only difference) If C.meth is the same function it was in the first version, then obviously whatever magic made c.meth() work in the first version will do the exact same thing here.
(This used to be slightly more complicated in Python 2, because of unbound methods, and classic classes too… but fortunately you don't have to worry about that.)
Finally, here's how you dynamically add a method to an instance:
class C:
pass
c = C()
c.x = 3
def meth(self):
print(self.x)
c.meth = types.MethodType(meth, c)
c.meth()
Here, you actually have to know the magic that makes c.meth() work in the first two cases. So read the Descriptor HOWTO. After that, it should be obvious.
But if you just want to pretend that Guido is a wizard (Raymond definitely is a wizard) and it's magic… Well, in the first two versions, Guido's magic wand creates a special bound method object whenever you ask for c.meth, but even he isn't magical enough to do that when C.meth doesn't exist. But we can painstakingly create that same bound method object and store it as c.meth. After that, we're going to get the same thing we stored whenever we ask for c.meth, which we explicitly built as the same thing we got in the first two examples, so it'll obviously do the same thing.
But what if we did this:
class C:
pass
c = C()
c.x = 3
def meth(self):
print(self.x)
c.meth = meth
c.meth(c)
Here, you're not letting Guido do his descriptor magic to create c.meth, and you're not doing it manually, you're just sticking a regular function there. Which means if you want anything to show up as the self parameter, you have to explicitly pass it as an argument, as in that silly c.meth(c) line at the end. But if you're willing to do that, then even this one works. No matter how self ends up as c, self.x is going to be c.x.
If I have this:
class foo(object):
#property
def bar(self):
return 0
f = foo()
How do I get a reference to f.bar without actually invoking the method, if this is even possible?
Edited to add: What I want to do is write a function that iterates over the members of f and does something with them (what is not important). Properties are tripping me up because merely naming them in getattr() invokes their __get__() method.
get_dict_attr (below) looks up attr in a given object's __dict__, and returns the associated value if its there. If attr is not a key in that __dict__, the object's MRO's __dict__s are searched. If the key is not found, an AttributeError is raised.
def get_dict_attr(obj, attr):
for obj in [obj] + obj.__class__.mro():
if attr in obj.__dict__:
return obj.__dict__[attr]
raise AttributeError
For example,
class Foo(object):
x=1
def bar(self):
pass
#property
def baz(self):
return 0
foo=Foo()
print(get_dict_attr(foo,'x'))
# 1
print(get_dict_attr(foo,'bar'))
# <unbound method Foo.bar>
print(get_dict_attr(foo,'baz'))
# <property object at 0xb77c0dc4>
print(get_dict_attr(foo,'y'))
# AttributeError
Note that this is very different than the normal rules of attribute lookup.
For one thing, data-descriptors in obj.__class__.__dict__ (descriptors with both __get__ and __set__ methods) normally have precedence over values in obj.__dict__. In get_dict_attr, obj.__dict__ has precedence.
get_dict_attr does not try calling __getattr__.
Finally, get_dict_attr will only work with objects obj which are instances of new-style classes.
Nevertheless, I hope it is of some help.
class Foo(object):
#property
def bar(self):
return 0
f = Foo()
This references the property bar:
print(Foo.bar)
# <property object at 0xb76d1d9c>
You see bar is a key in Foo.__dict__:
print(Foo.__dict__['bar'])
# <property object at 0xb775dbbc>
All properties are descriptors, which implies it has a __get__ method:
print(Foo.bar.__get__)
# <method-wrapper '__get__' of property object at 0xb76d7d74>
You can call the method by passing the object f, and the class of f as arguments:
print(Foo.bar.__get__(f,Foo))
# 0
I am fond of the following diagram. Vertical lines show the relationship between an object and the object's class.
When you have this situation:
Foo B
| Foo.__dict__={'bar':b} | B.__dict__={'__get__':...}
| \ |
f `--------> b
f.bar causes b.__get__(f,Foo) to be called.
This is explained in detail here.
Short answer:
Properties return its self when they called from class: MyClass.my_prop
Also, they have fields that contain a link to the actual methods: fget, fset and fdel.
Description:
So, my_class.my_prop (where my_class = MyClass()) returns the value, but MyClass.my_prop returns the property object and MyClass.my_prop.fget returns the getter method of this property. The self is not linked to it, so it should be populated during the call: MyClass.my_prop.fget(my_class)
Example:
class MyClass:
my_prop = property(lambda self: 'get', lambda self, x: print('set', x))
setter = MyClass.my_prop.fset
getter = MyClass.my_prop.fget
my_class = MyClass()
setter(my_class, 5) # equals my_class.my_prop = 5
print(getter(my_class)) # equals print(my_class.my_prop)
I ran into a similar situation to this and none of the other answers helped me, so here's an alternate approach.
My situation was slightly different, as instead of just having a #property, I was mixing in a custom decorator that adds attributes to the wrapped method. So eg normally I'd have something like this:
class Foo:
#my_decorator
def bar(self):
return do_stuff() # Pretend this is non-trivial
My #my_decorator would then give me access to self.bar.my_attribute that had some data I need to access sometimes. This works great for functions and methods, but I hit a snag when trying to mix it with #property because the property hides the reference to the method (self.bar.my_attribute fails because self.bar returns the return value of the method, which doesn't have the my_attribute that I want).
I'd use #property as the outer decorator like so:
class Foo:
#property
#my_decorator
def bar(self):
return do_stuff() # Pretend this is non-trivial
And then the solution is to access my_attribute as Foo.bar.fget.my_attribute (the important detail here is that accessing the property from the class returns the property object, whereas accessing the property from an instance just calls the method and returns the value, without access to the reference to the original method).
TL;DR: If you need a reference to the method that provides your #property, you need to use YourClassName.your_property.fget.
In your case,
class Foo(object):
#property
def bar(self):
return 0
f = Foo()
You can access the property through the class Foo. These are all equivalent:
Foo.bar
Foo.__dict__['bar']
f.__class__.__dict__['bar']
=> <property at 0x4920c28>
As you can see, this is a property instance. On a property you have a method called fget which returns the 'getter' value.
isinstance(Foo.bar, property)
=> True
Foo.bar.fget
=> <function Foo.bar at 0x0000014DC0CF21F0>
You can call this function (an instance method) directly.
Foo.bar.fget(f)
=> 0
Note: you have to supply the object f (the self argument) to fget yourself, because when accessed through the class, the class does not know the instance f yet. In other words, instance method Foo.bar.fget is not yet 'bound' to f.
One thing you should know is that data descriptors (i.e., properties) only work when they are applied to (new-style) classes (see http://docs.python.org/reference/datamodel.html#implementing-descriptors). Copying them to an object will not create the property on that object. You need to copy them to a (new-style) class to take effect.
Why not just lambdify it?
bar_getter = lambda: f.bar
Done.
I'm going to say ignore the other answers because they are bad.
You can get a reference to the property simply by foo.bar
As for what you're trying to do iterating over the members of f, see below for specifics.
The long answer: what you have to understand are that methods in Python do not belong to instances, but are attributes of the class object. For example,
class Foo:
def bar(self):
pass
foo = Foo()
if you call foo.bar(), Python first checks to see if foo has bar (it doesn't), then it checks if Foo has bar, which it does. Python then "binds" foo.bar to Foo.bar(foo), and calls that.
The same is true for properties. I don't know the exact process (and I imagine it differs between implementations), but essentially Python looks for foo.bar, then Foo.bar, sees that it is a property, so evaluates its getter and returns that.