How can I extend a builtin class in python?
I would like to add a method to the str class.
I've done some searching but all I'm finding is older posts, I'm hoping someone knows of something newer.
Just subclass the type
>>> class X(str):
... def my_method(self):
... return int(self)
...
>>> s = X("Hi Mom")
>>> s.lower()
'hi mom'
>>> s.my_method()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in my_method
ValueError: invalid literal for int() with base 10: 'Hi Mom'
>>> z = X("271828")
>>> z.lower()
'271828'
>>> z.my_method()
271828
One way could be to use the "class reopening" concept (natively existing in Ruby) that can be implemented in Python using a class decorator.
An exemple is given in this page:
http://www.ianbicking.org/blog/2007/08/opening-python-classes.html
I quote:
I think with class decorators you could do this:
#extend(SomeClassThatAlreadyExists)
class SomeClassThatAlreadyExists:
def some_method(self, blahblahblah):
stuff
Implemented like this:
def extend(class_to_extend):
def decorator(extending_class):
class_to_extend.__dict__.update(extending_class.__dict__)
return class_to_extend
return decorator
Assuming that you can not change builtin classes.
To simulate a "class reopening" like Ruby in Python3 where __dict__ is an mappingproxy object and not dict object :
def open(cls):
def update(extension):
for k,v in extension.__dict__.items():
if k != '__dict__':
setattr(cls,k,v)
return cls
return update
class A(object):
def hello(self):
print('Hello!')
A().hello() #=> Hello!
#reopen class A
#open(A)
class A(object):
def hello(self):
print('New hello!')
def bye(self):
print('Bye bye')
A().hello() #=> New hello!
A().bye() #=> Bye bye
In Python2 I could also write a decorator function 'open' as well:
def open(cls):
def update(extension):
namespace = dict(cls.__dict__)
namespace.update(dict(extension.__dict__))
return type(cls.__name__,cls.__bases__,namespace)
return update
Related
I have a code like this:
class Base:
def __init__(self):
pass
def new_obj(self):
return Base() # ← return Derived()
class Derived(Base):
def __init__(self):
pass
In the line with a comment I actually want not exactly the Derived object, but any object of class that self really is.
Here is a real-life example from Mercurial.
How to do that?
def new_obj(self):
return self.__class__()
I can't think of a really good reason to do this, but as D.Shawley pointed out:
def new_obj(self):
return self.__class__()
will do it.
That's because when calling a method on a derived class, if it doesn't exist on that class, it will use the method resolution order to figure out which method to call on its inheritance chain. In this case, you've only got one, so it's going to call Base.new_obj and pass in the instance as the first argument (i.e. self).
All instances have a __class__ attribute, that refers to the class that they are an instance of. So given
class Base:
def new_obj(self):
return self.__class__()
class Derived(Base): pass
derived = Derived()
The following lines are functionally equivalent:
derived.new_obj()
# or
Base.new_obj(derived)
You may have encountered a relative of this if you've either forgotten to add the self parameter to your function declaration, or not provided enough arguments to a function and seen a stack trace that looks like this:
>>> f.bar()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bar() takes exactly 2 arguments (1 given)
You can use a classmethod:
class Base:
def __init__(self):
pass
#classmethod
def new_obj(cls):
return cls()
class Derived(Base):
def __init__(self):
pass
>>> b = Base()
>>> b.new_obj()
<__main__.Base at 0x10fc12208>
>>> d = Derived()
>>> d.new_obj()
<__main__.Derived at 0x10fdfce80>
You can also do this with a class method, which you create with a decorator.
In [1]: class Base:
...: #classmethod
...: def new_obj(cls):
...: return cls()
...:
In [2]: class Derived(Base): pass
In [3]: print type(Base.new_obj())
<type 'instance'>
In [4]: print Base.new_obj().__class__
__main__.Base
In [5]: print Derived.new_obj().__class__
__main__.Derived
Incidentally (you may know this), you don't have to create __init__ methods if you don't do anything with them.
I'm attempting to create a dictionary of executable functions within a class. But having trouble getting the self parameter to work correctly.
Consider the following code:
class myclass(object):
def x(self):
return 'x'
def y(self):
return 'y'
EF= {
'a':x,
'b':y,
}
def test(self):
print self.EF['a']()
When I attempt to execute the 'test' function of the class, I get an error around the number of parameters as it evaluates and executes one of the functions in the dictionary.
>>> class myclass(object):
... def x(self):
... return 'x'
... def y(self):
... return 'y'
... EF= {
... 'a':x,
... 'b':y,
... }
... def test(self):
... print self.EF['a']()
...
>>>
>>>
>>> m=myclass()
>>> m.test()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 11, in test
TypeError: x() takes exactly 1 argument (0 given)
I've tried a few variations, including this which doesn't work.
EF= {
'a':self.x,
'b':self.y,
}
The only thing that did work was when I explicitly passed self as a parameter, like this.
... def test(self):
... print self.EF['a'](self)
...
>>> m=myclass()
>>> m.test()
x
I've seen other questions about using a dictionary to index functions, but none from within a class.
Here are my questions:
What is the proper way to do handle the self parameter?
I'd prefer to move my dictionary constant outside of the class into my constants section. Can I do that, and if so how? Should I do that?
If I should/have to have my dictionary within my class, why can't I move it to the top of the class?
That's all I got. Thanks for the help.
What is the proper way to do handle the self parameter?
Python uses the self identifier in similar ways to other imperative languages using the this identifier, but it is explicit (as explicit is better than implicit!)
This allows you to use the class as either an instantiated object, or the static class itself.
For an instantiated version, you are probably looking for
>>> class myclass:
def __init__(self):
self.EF = {'a':self.x,'b':self.y}
def x(self):
return 'x'
def y(self):
return 'y'
def test(self):
print self.EF['a']()
>>> my_test_class = myclass()
>>> my_test_class.test()
x
I'd prefer to move my dictionary constant outside of the class into my constants section. Can I do that, and if so how? Should I do that?
If you wanted to use them as static method in a dict outside your class definition, you would need to use the #staticmethod decorator
>>> class myclass(object):
#staticmethod
def x():
return 'x'
#staticmethod
def y():
return 'y'
>>> EF = {'a':myclass.x,'b':myclass.y}
>>> EF['a']()
'x'
If I should/have to have my dictionary within my class, why can't I move it to the top of the class?
Any object attributes should be defined either in the __init__ function, or by explicitly setting them.
Having the dictionary in an init method will make it work
class Myclass(object):
def x(self):
return 'x'
def y(self):
return 'y'
def __init__(self):
self.EF= {
'a':self.x,
'b':self.y
}
def test(self):
print self.EF['a']()
m=Myclass()
m.test()
In reference to your questions. The class is kind of a dictionary or named tuple of attributes and executable functions. The functions themselves only define behavior. self is a sack of state related to your instance. if you save a pointer to that function somewhere else and provide it with a given self that is an instance of your class it should work as normal.
class MyClass(object):
def __init__(self, x):
self.x = x
def fun(self):
return self.x
i = MyClass(1)
print i.fun()
f = MyClass.fun
i2 = MyClass(2)
print f(i2)
When you call using the standard i.fun() all it's doing is passing i in implicitly as the selfargument.
I would like to write a decorator for a python class method that can determine if the method was called from a public context or private context. For example, given the following code
def public_check_decorator(f):
def wrapper(self):
if self.f is `called publicly`: # <-- how do I make this line work correctly?
print 'called publicly'
else:
print 'called privately'
return f(self)
return wrapper
class C(object):
#public_check_decorator
def public_method(self):
pass
def calls_public_method(self):
self.public_method()
runtime execution would ideally look something like this:
>>> c = C()
>>> c.public_method()
called publicly
>>> c.calls_public_method()
called privately
Is there any way to do this in python? That is, alter the line
if self.f is `called publicly`: # <-- how do I make this line work correctly?
to give the desired output?
Given the name of the package decides whether a function is being called from a private context or public one:
import inspect
import re
def run():
package_name = '/my_package/'
p = re.match(r'^.*' + package_name, inspect.stack()[0].filename).group()
is_private_call = any(re.match(p, frame.filename) is not None for frame in inspect.stack()[1:])
print(is_private_call)
Try running from within the package and then from outside the package!!!
see inspect.stack()
Some of this seems like trying to swim against the current of "python". Is that appropriate?
Do you know about the double-unscore standard? It makes methods "more private":
>>> class C(object):
... def __hide_me(self):
... return 11
... def public(self):
... return self.__hide_me()
...
>>> c = C()
>>> c.__hide_me()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'C' object has no attribute '__hide_me'
>>> c.public()
11
>>> c._C__hide_me()
11
>>>
Is that private enough? And using this technique is pythonic.
Recently, I encountered a problem with metaclass calling a derived classmethod.
For example, I get a simple baseclass testA, which has an classmethod do1(a)
class testA(object):
#classmethod
def do1(cls, a):
print "in testA:",cls, a
Then I build a metaclass which actually do nothing but print the cls:
class testMetaA(type):
def __init__(cls,cname,bases,cdict):
print "in testMetaA: %s"%cls
Then I could use the metaclass to build a subclass testB, which works as expected:
class testB(testA):
#classmethod
def do1(cls, a):
print "in testB: %s"%cls
super(testB, cls).do1(a)
__metaclass__=testMetaA
It will print: in testMetaA: <class '__main__.testB'>; and the testB.do1(a) works as expected:
>>> testB.do1('hello')
in testB: <class '__main__.testB'>
in testA: <class '__main__.testB'> hello
However, if I try to call the classmethod inside the metaclass which contains a "super" as following testMetaB, it will raise an error: NameError: global name 'testC' is not defined.
class testMetaB(type):
def __init__(cls,cname,bases,cdict):
print "in testMetaB: %s"%cls
cls.do1("hello")
class testC(testA):
#classmethod
def do1(cls, a):
print "in testC: %s"%cls
super(testC, cls).do1(a)
__metaclass__=testMetaB
I finally find a way to solve it by use super(cls, cls) instead of super(testC, cls):
class testD(testA):
#classmethod
def do1(cls, a):
print "in testD: %s"%cls
super(cls, cls).do1(a)
__metaclass__=testMetaB
It will print as:
in testMetaB: <class '__main__.testD'>
in testD: <class '__main__.testD'>
in testA: <class '__main__.testD'> hello
The testD.do1(a) also works as expected:
>>> testD.do1('Well done')
in testD: <class '__main__.testD'>
in testA: <class '__main__.testD'> Well done
Now I am wondering which is the most correct way to use super in a classmethod? Should one always use super(cls,cls) instead of explicitly writing a current class name?
Thanks!
#jsbueno
If some piece of code resorts to tricks like dynamically creating derived classes, that is important - one should not use the class name as first parametere to Super if that name is assigned to another object than the class itself. Instead, cls for class methods, or self.__class__ for instance methods can be passed to Super.
Does this means it is a bad idea to use class name to super in general?
To myself, I usually use super(type(self),self) instead of super(type(self.__class__),self) for normal method. I do not know if there is any major advantage to use self.__class__.
I repeat #jsbueno example like this, here the C use super(type(self),self). So D2() will not change the behavior while the class C gets changed.
>>> class A(object):
def do(self):
print "in class A"
>>> class B(A):
def do(self):
super(B, self).do()
>>> class C(A):
def do(self):
super(type(self),self).do()
>>> D1=B
>>> D2=C
>>> D1().do()
in class A
>>> D2().do()
in class A
>>> class B(A):
def do(self):
print "in new class B"
>>> D1().do()
Traceback (most recent call last):
File "<pyshell#52>", line 1, in <module>
D1().do()
File "<pyshell#37>", line 3, in do
super(B, self).do()
TypeError: super(type, obj): obj must be an instance or subtype of type
>>> class C(A):
def do(self):
print "in new class C"
>>> D2().do()
in class A
according to #Don Question's suggestion, I put the python version here: sys.version= 2.7.2+ (default, Oct 4 2011, 20:06:09) [GCC 4.6.1]
However, if I try to call the classmethod inside the metaclass which
contains a "super" as following testMetaB, it will raise an error:
NameError: global name 'testC' is not defined.
The name TestC will only be bound to the new class after the MetaClass finished it's work - and that is after returning from it's __init__ (and before __init__, the __new__) method.
When we use the "super" call usign the class name as the first parameter, the class name does not appear there magically: it is a (module) global variable, to which the class itself is assigned - in normal circunstances.
In this case, the name has not been assigned yet - however, as it is a classmethod, yuu have a reference to the class in the cls variable- that is why it works.
If some piece of code resorts to tricks like dynamically creating derived classes, that is important - one should not use the class name as first parametere to Super if that name is assigned to another object than the class itself. Instead, cls for class methods, or self.__class__ for instance methods can be passed to Super.
Here is a snippet showing the global name binding for the class name is what super takes:
>>> class A(object):
... def do(self):
... print "In class A"
...
>>> class B(A):
... def do(self):
... super(B, self).do()
...
>>> C = B
>>> C().do()
In class A
>>> class B(object):
... def do(self):
... print "in new class B"
...
>>> C().do()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in do
TypeError: super(type, obj): obj must be an instance or subtype of type
>>>
Suppose one decided (yes, this is horrible) to create handle input in the following manner: A user types in a command on the python console after importing your class, the command is actually a class name, the class name's __str__ function is actually a function with side effects (e.g. the command is "north" and the function changes some global variables and then returns text describing your current location). Obviously this is a stupid thing to do, but how would you do it (if possible)?
Note that the basic question is how to define the __str__ method for a class without creating an instance of the class, otherwise it would be simple (but still just as crazy:
class ff:
def __str__(self):
#do fun side effects
return "fun text string"
ginst = ff()
>>ginst
What you are looking for is the metaclass
class Magic(type):
def __str__(self):
return 'Something crazy'
def __repr__(self):
return 'Another craziness'
class Foo(object):
__metaclass__ = Magic
>>> print Foo
Something crazy
>>> Foo
Another craziness
in console you're getting representation of your object, which __repr__ is responsible for. __str__ used for printing:
>>> class A:
def __str__(self):
return 'spam'
>>> A()
<__main__.A object at 0x0107E3D0>
>>> print(A())
spam
>>> class B:
def __repr__(self):
return 'ham'
>>> B()
ham
>>> print(B())
ham
>>> class C:
def __str__(self):
return 'spam'
def __repr__(self):
return 'ham'
>>> C()
ham
>>> print(C())
spam
You could use instances of a class rather than classes themselves. Something like
class MagicConsole(object):
def __init__(self, f):
self.__f = f
def __repr__(self):
return self.__f()
north = MagicConsole(some_function_for_north)
south = MagicConsole(some_function_for_south)
# etc