class a(object):
def a(self):
return True
__contains__=a
b=a()
print 2 in b#why error
__contains__ is meant to take an argument. a doesn't accept an argument.
The following is your example with a working __contains__:
>>> class a(object):
... def a(self, item):
... return True
... __contains__=a
...
>>> b=a()
>>> print 2 in b
True
The signature of __contains__ is:
object.__contains__(self, item)
as per documentation. You need to extend your "a" method:
def a(self, item)
class a(object):
def a(self, item):
return True
__contains__=a
Related
I'm using a decorator for singletons in python, implemented as shown below.
I'd like to have the pydoc of the decorated class being exactly the same as the pydoc of the non decorated class, but I don't find how:
Without the getSingletonInstance.__doc__ = cls.__doc__ line, the pydoc of the decorated class gives the pydoc of the singleton function.
With the getSingletonInstance.__doc__ = cls.__doc__ line, the pydoc of the decorated class gives only the "top level" docstring.
How can I proceed?
Thanks.
def singleton(cls):
"""A singleton decorator
Warnings
--------
Singleton gdecorated calsses cannot be inhehited
Example
-------
>>> from decorators import singleton
>>> #singleton
... class SingletonDemo():
... pass
>>> d1 = SingletonDemo()
>>> d1.a = 0xCAFE
>>> d2 = SingletonDemo()
>>> id(d1) == id(d2)
True
>>> d1 == d2
True
>>> d2.a == 0xCAFE
True
References
----------
See case 2 of https://www.python.org/dev/peps/pep-0318/#examples
"""
_instances = {}
def getSingletonInstance():
if cls not in _instances:
_instances[cls] = cls()
return _instances[cls]
getSingletonInstance.__doc__ = cls.__doc__
return getSingletonInstance
Try using functools.wraps:
import functools
def wrapper(cls):
_instances = {}
class inner(cls):
def __new__(subcls):
if subcls not in _instances:
_instances[subcls] = object.__new__(subcls)
return _instances[subcls]
inner.__doc__=cls.__doc__
return inner
#wrapper
class A(object):
"""Example Docstring"""
def method(self):
"""Method Docstring"
A.__doc__
# "Example Docstring"
A.method.__doc__
# "Method Docstring"
Answer summarizing all the discussions, with example.
Thanks a lot to everybody.
This solution:
Preserves the docstring
Preserves the type
Supports static and class methods
Limitations:
Singletons cannot be inherited, which is meaningful regarding to the context
Solution:
def singleton(cls):
"""A singleton decorator
Warnings
--------
Singleton decorated classes cannot be inhehited
Example
-------
>>> import abc
>>>
>>> #singleton
... class A():
... "Ad-hoc documentation of class A"
... def __init__(self):
... "Ad-hoc documentation of class A constructor"
... print("constructor called")
... self.x = None
... #classmethod
... def cm(cls):
... "a class method"
... print("class method called")
... def im(self):
... "an instance method"
... print("instance method called")
... #staticmethod
... def sm():
... "a static method"
... print("static method called")
...
>>> #singleton
... class P(abc.ABCMeta):
... #abc.abstractmethod
... def __init__(self):
... pass
...
>>> class C(P):
... def __init__(self):
... print("C1 constructor called")
...
>>> a1 = A()
constructor called
>>> a1.x = 0xCAFE
>>> a1.x
51966
>>> a2 = A()
>>> a2.x
51966
>>> a1.x == a2.x
True
>>> a1 == a2
True
>>> id(a1) == id(a2)
True
>>> type(a1) == type(a2)
True
>>> isinstance(a1, A)
True
>>> ta1 = type(a1)
>>> issubclass(ta1, A)
True
>>> A.cm()
class method called
>>> a1.cm()
class method called
>>> A.sm()
static method called
>>> a1.sm()
static method called
>>> a1.im()
instance method called
>>> try:
... C()
... except Exception as e:
... type(e)
...
<class 'TypeError'>
"""
_instances = {}
_constructorCalled = []
class inner(cls):
def __new__(subcls):
if subcls not in _instances:
_instances[subcls] = cls.__new__(subcls)
return _instances[subcls]
def __init__(self):
if type(self) not in _constructorCalled:
cls.__init__(self)
_constructorCalled.append(type(self))
__init__.__doc__ = cls.__init__.__doc__
__new__.__doc__ = cls.__new__.__doc__
if __new__.__doc__ == (
"Create and return a new object. "
"See help(type) for accurate signature."
):
__new__.__doc__ = "Returns a singleton instance"
inner.__doc__ = cls.__doc__
return inner
class A:
x=1
def __add__(self, obj):
if isinstance(obj,A):
return self.x+obj.x
return "False"
class B(A):
x=2
a=A()
b=B()
print(a+b)
The add method takes self, the first object in the addition, and another one, other.
For example:
class A:
def __init__(self, x):
self.x=x
def __add__(self, obj):
if isinstance(obj,A):
return self.x+obj.x
raise NotImplementedError
a = A(3)
b = A(4)
res = a + b # this is essentially a.__add__(obj=b)
# self is implicitly the object a
# res == 7
I want to inherit from class just to add decorators to its methods.
Is there a shortcut to do this without redefining each base class method?
You can use a class decorator to encapsulate the whole work
Example code:
def deco(func):
"""Function decorator"""
def inner(*args, **kwargs):
print("decorated version")
return func(*args, **kwargs)
return inner
def decoclass(decorator):
"""Class decorator: decorates public methods with decorator"""
def outer(cls):
class inner(cls):
pass
for name in dir(cls):
if not name.startswith("_"): # ignore hidden and private members
# print("decorating", name) # uncomment for tests
attr = getattr(inner, name)
setattr(inner, name, decorator(attr))
return inner
return outer
class Foo:
"""Sample class""
def foo(self):
return "foo in Foo"
You can then use it:
>>> #decoclass(deco)
class Foo2(Foo):
pass
>>> f = Foo2()
>>> f.foo()
decorated version
'foo in Foo'
Sure, you can do this dynamically. Suppose you have some class:
>>> class Foo:
... def bar(self): print('bar')
... def baz(self): print('baz')
...
And a decorator:
>>> def deco(f):
... def wrapper(self):
... print('decorated')
... return f(self)
... return wrapper
...
Then simply inherit:
>>> class Foo2(Foo):
... pass
...
Then loop over your original class, and apply the decorator to your new child-class:
>>> for name, attr in vars(Foo).items():
... if callable(attr):
... setattr(Foo2, name, deco(attr))
...
So...
>>> x = Foo2()
>>> x.bar()
decorated
bar
>>> x.baz()
decorated
baz
Now, using if callable(attr) might not be restrictive enough. You might want to ignore "dunder" methods, so instead:
for name, attr in vars(Foo):
if callable(attr) and not name.startswith('__'):
setattr(Foo2, name, attr)
might be more appropriate. Depends on your use-case.
And just for fun, here we can also use the type constructor:
In [17]: class Foo:
...: def bar(self): print('bar')
...: def baz(self): print('baz')
...:
In [18]: def deco(f):
...: def wrapper(self):
...: print('decorated')
...: return f(self)
...: return wrapper
...:
In [19]: Foo3 = type(
...: 'Foo3',
...: (Foo,),
...: {name:deco(attr) for name, attr in vars(Foo).items() if callable(attr)}
...: )
In [20]: y = Foo3()
In [21]: y.bar()
decorated
bar
In [22]: y.baz()
decorated
baz
Consider the following snippet of codes.
class MyClass(object):
#property
def foo(self):
return self._foo
l = [my_class1, my_class2]
min(l, key=MyClass.foo) # doesn't work because foo is not callable.
# "TypeError: 'property' object is not callable"
Is there a way to make it work?
Using operator.attrgetter:
min(l, key=operator.attrgetter('foo'))
Example:
>>> class MyClass(object):
... def __init__(self, val):
... self._foo = val
... def __repr__(self):
... return 'MyClass({})'.format(self._foo)
... #property
... def foo(self):
... return self._foo
...
>>> import operator
>>> min([MyClass(3), MyClass(1), MyClass(2)], key=operator.attrgetter('foo'))
MyClass(1)
You can use a lambda expression to access foo just as though it were an attribute:
min(l, key=lambda o: o.foo)
Since Python strives for there to be one right way, I'm wondering what the purpose of property.getter is. In this example WhyMe defines a getter but Other doesn't so I'm wondering what the point of property.getter is over just using property.
class WhyMe(object):
def __init__(self):
self._val = 44
#property
def val(self):
print 'I am not called'
return self._val
#val.getter # What advantage do I bring?
def val(self):
print 'getter called'
return self._val
class Other(object):
def __init__(self):
self._val = 44
#property
def val(self):
print 'I AM called'
return self._val
And using them:
>>> why = WhyMe()
>>> why.val
getter called
44
>>> other = Other()
>>> other.val
I AM called
44
I'm no stranger to properties, I'm just wondering if there is some advantage to making a getter or if was just put there for symmetry?
#property let's you define a whole new property, by defining a getter for that property. The #original.getter syntax lets you override just the existing getter. There are also .setter and .deleter decorators, to the other two methods available to a property.
Imagine you subclassing a custom class that is using a property, with both a getter and a setter defined. If you only wanted to override the getter of that property but leaving the setter in place (or the deleter), using #BaseClass.original.getter lets you do that:
>>> class Foo(object):
... #property
... def spam(self):
... print 'Foo.spam called'
... return 'spam'
... #spam.setter
... def spam(self, value):
... print 'Foo.spam.setter called'
... #property
... def ham(self):
... print 'Foo.ham called'
... return 'ham'
... #ham.setter
... def ham(self, value):
... print 'Foo.ham.setter called'
...
>>> class Bar(Foo):
... #Foo.spam.getter
... def spam(self):
... print 'Bar.spam override'
... return 'eggs and spam'
... #property
... def ham(self):
... print 'Bar.ham override'
... return 'eggs and ham'
...
>>> Bar().spam
Bar.spam override
'eggs and spam'
>>> Bar().spam = 'foo'
Foo.spam.setter called
>>> Bar().ham
Bar.ham override
'eggs and ham'
>>> Bar().ham = 'foo'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
Note that I only replaced the spam getter, while it's setter was preserved. The Bar.ham setter does not exist, I replaced the Foo.ham property wholesale.