I would like to do the following:
class A(object): pass
a = A()
a.__int__ = lambda self: 3
i = int(a)
Unfortunately, this throws:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: int() argument must be a string or a number, not 'A'
This only seems to work if I assign the "special" method to the class A instead of an instance of it. Is there any recourse?
One way I thought of was:
def __int__(self):
# No infinite loop
if type(self).__int__.im_func != self.__int__.im_func:
return self.__int__()
raise NotImplementedError()
But that looks rather ugly.
Thanks.
Python always looks up special methods on the class, not the instance (except in the old, aka "legacy", kind of classes -- they're deprecated and have gone away in Python 3, because of the quirky semantics that mostly comes from looking up special methods on the instance, so you really don't want to use them, believe me!-).
To make a special class whose instances can have special methods independent from each other, you need to give each instance its own class -- then you can assign special methods on the instance's (individual) class without affecting other instances, and live happily ever after. If you want to make it look like you're assigning to an attribute the instance, while actually assigning to an attribute of the individualized per-instance class, you can get that with a special __setattr__ implementation, of course.
Here's the simple case, with explicit "assign to class" syntax:
>>> class Individualist(object):
... def __init__(self):
... self.__class__ = type('GottaBeMe', (self.__class__, object), {})
...
>>> a = Individualist()
>>> b = Individualist()
>>> a.__class__.__int__ = lambda self: 23
>>> b.__class__.__int__ = lambda self: 42
>>> int(a)
23
>>> int(b)
42
>>>
and here's the fancy version, where you "make it look like" you're assigning the special method as an instance attribute (while behind the scene it still goes to the class of course):
>>> class Sophisticated(Individualist):
... def __setattr__(self, n, v):
... if n[:2]=='__' and n[-2:]=='__' and n!='__class__':
... setattr(self.__class__, n, v)
... else:
... object.__setattr__(self, n, v)
...
>>> c = Sophisticated()
>>> d = Sophisticated()
>>> c.__int__ = lambda self: 54
>>> d.__int__ = lambda self: 88
>>> int(c)
54
>>> int(d)
88
The only recourse that works for new-style classes is to have a method on the class that calls the attribute on the instance (if it exists):
class A(object):
def __int__(self):
if '__int__' in self.__dict__:
return self.__int__()
raise ValueError
a = A()
a.__int__ = lambda: 3
int(a)
Note that a.__int__ will not be a method (only functions that are attributes of the class will become methods) so self is not passed implicitly.
I have nothing to add about the specifics of overriding __int__. But I noticed one thing about your sample that bears discussing.
When you manually assign new methods to an object, "self" is not automatically passed in. I've modified your sample code to make my point clearer:
class A(object): pass
a = A()
a.foo = lambda self: 3
a.foo()
If you run this code, it throws an exception because you passed in 0 arguments to "foo" and 1 is required. If you remove the "self" it works fine.
Python only automatically prepends "self" to the arguments if it had to look up the method in the class of the object and the function it found is a "normal" function. (Examples of "abnormal" functions: class methods, callable objects, bound method objects.) If you stick callables in to the object itself they won't automatically get "self".
If you want self there, use a closure.
Related
Consider:
class A(object):
def f(self): print("A")
class B(A):
def f(self): print("B")
b = B()
I can call A.f on b by doing:
A.f(b)
Is there an easy way to "wrap" b such that wrap(b).f() calls A.f for any f?
Here is my solution which copies the methods from the most upper base class:
import types, copy
def get_all_method_names(clazz):
return [func for func in dir(clazz) if callable(getattr(clazz, func))]
def wrap(obj):
obj = copy.copy(obj)
obj_clazz = obj.__class__
base_clazz = obj_clazz.__bases__[-1] # the one which directly inherits from object
base_methods = get_all_method_names(base_clazz) # list of all method names in base_clazz
for base_method_name in base_methods:
base_method = getattr(base_clazz, base_method_name) # get the method object
if isinstance(base_method, types.FunctionType): # skip dunder methods like __class__, __init__
setattr(obj, base_method_name, base_method) # copy it into our object
return obj
# class declaration from question here
wrapped_b = wrap(b)
wrapped_b.f(wrapped_b) # prints A, unfortunately we have to pass the self parameter explicitly
b.f() # prints B, proof that the original object is untouched
This feels dirty to me, but it also seems to work. I'm not sure I'd rely on this for anything important.
import copy
def upcast(obj, clazz):
if not isinstance(obj, clazz): # make sure we're actually "upcasting"
raise TypeError()
wrapped = copy.copy(obj)
wrapped.__class__ = clazz
return wrapped
This results in
>>> a = A()
>>> a.f()
A
>>> b = B()
>>> b.f()
B
>>> upcast(b, A).f()
A
What I've really done here is essentially monkey-patch a clone of b and lied to it and told it it's actually an A, so when it comes time to resolve which version of f to call, it'll call the one from A.
Object Slicing is not supported in python the way it is done in C++ (The link you are pointing to takes a cpp example).
In Python Object Slicing is a rather different thing which means to slice up any object which supports sequence protocol (implements getitem() and len() methods).
Example :
A = [1,2,3,4,5,6,7,8]
print(A[1:3])
But in C++ Object Slicing is just cutting off the properties added by a base class instance when assigned to a parent class variable.
In my code I have a class, where one method is responsible for filtering some data. To allow customization for descendants I would like to define filtering function as a class attribute as per below:
def my_filter_func(x):
return x % 2 == 0
class FilterClass(object):
filter_func = my_filter_func
def filter_data(self, data):
return filter(self.filter_func, data)
class FilterClassDescendant(FilterClass):
filter_func = my_filter_func2
However, such code leads to TypeError, as filter_func receives "self" as first argument.
What is a pythonic way to handle such use cases? Perhaps, I should define my "filter_func" as a regular class method?
You could just add it as a plain old attribute?
def my_filter_func(x):
return x % 2 == 0
class FilterClass(object):
def __init__(self):
self.filter_func = my_filter_func
def filter_data(self, data):
return filter(self.filter_func, data)
Alternatively, force it to be a staticmethod:
def my_filter_func(x):
return x % 2 == 0
class FilterClass(object):
filter_func = staticmethod(my_filter_func)
def filter_data(self, data):
return filter(self.filter_func, data)
Python has a lot of magic within. One of those magics has something to do with transforming functions into UnboundMethod objects (when assigned to the class, and not to an class' instance).
When you assign a function (And I'm not sure whether it applies to any callable or just functions), Python converts it to an UnboundMethod object (i.e. an object which can be called using an instance or not).
Under normal conditions, you can call your UnboundMethod as normal:
def myfunction(a, b):
return a + b
class A(object):
a = myfunction
A.a(1, 2)
#prints 3
This will not fail. However, there's a distinct case when you try to call it from an instance:
A().a(1, 2)
This will fail since when an instance gets (say, internal getattr) an attribute which is an UnboundMethod, it returns a copy of such method with the im_self member populated (im_self and im_func are members of UnboundMethod). The function you intended to call, is in the im_func member. When you call this method, you're actually calling im_func with, additionally, the value in im_self. So, the function needs an additional parameter (the first one, which will stand for self).
To avoid this magic, Python has two possible decorators:
If you want to pass the function as-is, you must use #staticmethod. In this case, you will have the function not converted to UnboundMethod. However, you will not be able to access the calling class, except as a global reference.
If you want to have the same, but be able to access the current class (disregarding whether the function it is called from an instance or from a class), then your function should have another first argument (INSTEAD of self: cls) which is a reference to the class, and the decorator to use is #classmethod.
Examples:
class A(object):
a = staticmethod(lambda a, b: a + b)
A.a(1, 2)
A().a(1, 2)
Both will work.
Another example:
def add_print(cls, a, b):
print cls.__name__
return a + b
class A(object):
ap = classmethod(add_print)
class B(A):
pass
A.ap(1, 2)
B.ap(1, 2)
A().ap(1, 2)
B().ap(1, 2)
Check this by yourseld and enjoy the magic.
I would something like this in Python:
result = SomeClass(some_argument)
Here is the catch though. I don't want the result to be an instance but an immutable object (int, for example). Basically the hole role of a class is returning a value calculated from the argument. I am using a class and not a function for DRY purposes.
Since the above code won't work because it will always return an instance of SomeClass what would be the best alternative?
My only idea is to have a static method, but I don't like it:
result = SomeClass.static_method(some_argument)
You can override __new__. This is rarely a good idea and/or necessary though ...
>>> class Foo(object):
... def __new__(cls):
... return 1
...
>>> Foo()
1
>>> type(Foo())
<type 'int'>
If you don't return an instance of cls, __init__ will never be called.
Basically class methods are the way to go if you have a factory method.
About the result - it really depends on what kind of immutability you seek, but basically namedtuple does a great job for encapsulating things and is also immutable (like normal tuples):
from collections import namedtuple
class FactoryClass(object):
_result_type = namedtuple('ProductClass', ['prod', 'sum'])
#classmethod
def make_object(cls, arg1, arg2):
return cls._result_type(prod=arg1 * arg2, sum=arg1 + arg2)
>>> FactoryClass.make_object(2,3)
ProductClass(prod=6, sum=5)
>>> x = _
>>> x.prod = 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
This isn't for anything I'm working on yet, it's just some test code as I'm just learning class methods and suck. But say I have the following code
class Test(int):
def __init__(self,arg):
self = arg
def thing(self):
self += 10
and going,
foo=Test(12) sets foo to 12. However I want it, so when I do, foo.thing(), foo increases by 10. So far, going foo.thing() just keeps it at 12. How would I change this code to do that.
Because int is a immutable, you cannot magically turn it into a mutable type.
Your methods are no-ops. They change self in the local namespace, by reassigning it to something else. They no longer point to the instance. In other words, both methods leave the original instance unaltered.
You cannot do what you want to do with a subclass of int. You'll have to create a custom class from scratch using the numeric type hooks instead.
Background: int has a __new__ method that assigns the actual value to self, and there is no __iadd__ method to support in-place adding. The __init__ method is not ignored, but you can leave it out altogether since __new__ already did the work.
Assigning to self means you just replaced the reference to the instance with something else, you didn't alter anything about self:
>>> class Foo(int):
... def __init__(self, value=0):
... print self, type(self)
... self = 'foobar'
... print type(self)
...
>>> foo = Foo(10)
10 <class '__main__.Foo'>
<type 'str'>
>>> print foo, type(foo)
10 <class '__main__.Foo'>
Because int does not have a __iadd__ in-place add method, your self += 2 is interpreted as self = self + 2 instead; again, you are assigning to self and replacing it with a new value altogether.
Say I am declaring a class C and a few of the declarations are very similar. I'd like to use a function f to reduce code repetition for these declarations. It's possible to just declare and use f as usual:
>>> class C(object):
... def f(num):
... return '<' + str(num) + '>'
... v = f(9)
... w = f(42)
...
>>> C.v
'<9>'
>>> C.w
'<42>'
>>> C.f(4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unbound method f() must be called with C instance as first argument (got int instance instead)
Oops! I've inadvertently exposed f to the outside world, but it doesn't take a self argument (and can't for obvious reasons). One possibility would be to del the function after I use it:
>>> class C(object):
... def f(num):
... return '<' + str(num) + '>'
... v = f(9)
... del f
...
>>> C.v
'<9>'
>>> C.f
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: type object 'C' has no attribute 'f'
But what if I want to use f again later, after the declaration? It won't do to delete the function. I could make it "private" (i.e., prefix its name with __) and give it the #staticmethod treatment, but invoking staticmethod objects through abnormal channels gets very funky:
>>> class C(object):
... #staticmethod
... def __f(num):
... return '<' + str(num) + '>'
... v = __f.__get__(1)(9) # argument to __get__ is ignored...
...
>>> C.v
'<9>'
I have to use the above craziness because staticmethod objects, which are descriptors, are not themselves callable. I need to recover the function wrapped by the staticmethod object before I can call it.
There has got to be a better way to do this. How can I cleanly declare a function in a class, use it during its declaration, and also use it later from within the class? Should I even be doing this?
Quite simply, the solution is that f does not need to be a member of the class. I am assuming that your thought-process has gone through a Javaish language filter causing the mental block. It goes a little something like this:
def f(n):
return '<' + str(num) + '>'
class C(object):
v = f(9)
w = f(42)
Then when you want to use f again, just use it
>>> f(4)
'<4>'
I think the moral of the tale is "In Python, you don't have to force everything into a class".
Extending Ali A's answer,
if you really want to avoid f in the module namespace (and using a non-exported name like _f, or setting __all__ isn't sufficient), then
you could achieve this by creating the class within a closure.
def create_C():
def f(num):
return '<' + str(num) + '>'
class C(object):
v = f(9)
def method_using_f(self, x): return f(x*2)
return C
C=create_C()
del create_C
This way C has access to f within its definition and methods, but nothing else does (barring fairly involved introspection
of its methods (C.method_using_f.im_func.func_closure))
This is probably overkill for most purposes though - documenting that f is internal by using the "_" prefix nameing convention should
generally be sufficient.
[Edit] One other option is to hold a reference to the pre-wrapped function object in the methods you wish to use it in. For example, by setting it as a default argument:
class C(object):
def f(num):
return '<' + str(num) + '>'
v = f(9)
def method_using_f(self, x, f=f): return f(x*2)
del f
(Though I think the closure approach is probably better)
I believe you are trying to do this:
class C():
... class F():
... def __call__(self,num):
... return "<"+str(num)+">"
... f=F()
... v=f(9)
>>> C.v
'<9>'
>>> C.f(25)
'<25>'
>>>
Maybe there is better or more pythonic solution...
"declare a function in a class, use it during its declaration, and also use it later from within the class"
Sorry. Can't be done.
"Can't be done" doesn't seem to get along with Python
This is one possibility:
class _C:
# Do most of the function definitions in here
#classmethod
def f(cls):
return 'boo'
class C(_C):
# Do the subsequent decoration in here
v = _C.f()
One option: write a better staticmethod:
class staticfunc(object):
def __init__(self, func):
self.func = func
def __call__(self, *args, **kw):
return self.func(*args, **kw)
def __repr__(self):
return 'staticfunc(%r)' % self.func
Let's begin from the beginning.
"declare a function in a class, use it during its declaration, and also use it later from within the class"
Sorry. Can't be done. "In a class" contradicts "used during declaration".
In a class means created as part of the declaration.
Used during declaration means it exists outside the class. Often as a meta class. However, there are other ways.
It's not clear what C.w and C.v are supposed to be. Are they just strings? If so, an external function f is the best solution. The "not clutter the namespace" is a bit specious. After all, you want to use it again.
It's in the same module as C. That's why Python has modules. It binds the function and class together.
import myCmod
myCmod.C.w
myCmod.C.v
myCmod.f(42)
If w and v aren't simple strings, there's a really good solution that gives a lot of flexibility.
Generally, for class-level ("static") variables like this, we can use other classes. It's not possible to completely achieve the desired API, but this is close.
>>> class F(object):
def __init__( self, num ):
self.value= num
self.format= "<%d>" % ( num, )
>>> class C(object):
w= F(42)
v= F(9)
>>> C.w
<__main__.F object at 0x00C58C30>
>>> C.w.format
'<42>'
>>> C.v.format
'<9>'
The advantage of this is that F is a proper, first-class thing that can be extended. Not a "hidden" thing that we're trying to avoid exposing. It's a fact of life, so we might as well follow the Open/Closed principle and make it open to extension.