In python I can do:
exec(code_string, globals(), some_object.__dict__)
to add a method to an object. Is it possible to add a static method to a class in some sort of similar fashion? Like:
exec(code_string, globals(), ClassName.__dict__)
So that I could then statically call the method:
ClassName.some_static_method()
What I'm trying to do is add new staticmethods during runtime given some python code defining the method. i.e. if I was given:
code_string = '''
#staticmethod
def test():
return 'blah'
'''
how can I create and instantiate this into a class so that I could call it?
Hopefully I was clear enough, thank you!
EDIT:
working example of adding a function to an object:
class TestObject(object):
pass
code_string = '''
def test():
return 'blah'
'''
t = TestObject()
exec(code_string, globals(), t.__dict__)
Use setattr()
>>> code_string = '''
... #staticmethod
... def test():
... return 'returning blah'
... '''
>>>
>>> exec(code_string)
>>> test
<staticmethod object at 0x10fd25c58>
>>> class ClassName(object):
... def instancemethod(self):
... print "instancemethod!"
...
>>> setattr(ClassName, 'teststaticmethod', test)
>>> ClassName.teststaticmethod()
'returning blah'
>>>
And here's an article on being safe with exec() and eval() in python.
Related
assume following class definition:
class A:
def f(self):
return 'this is f'
#staticmethod
def g():
return 'this is g'
a = A()
So f is a normal method and g is a static method.
Now, how can I check if the funcion objects a.f and a.g are static or not? Is there a "isstatic" funcion in Python?
I have to know this because I have lists containing many different function (method) objects, and to call them I have to know if they are expecting "self" as a parameter or not.
Lets experiment a bit:
>>> import types
>>> class A:
... def f(self):
... return 'this is f'
... #staticmethod
... def g():
... return 'this is g'
...
>>> a = A()
>>> a.f
<bound method A.f of <__main__.A instance at 0x800f21320>>
>>> a.g
<function g at 0x800eb28c0>
>>> isinstance(a.g, types.FunctionType)
True
>>> isinstance(a.f, types.FunctionType)
False
So it looks like you can use types.FunctionType to distinguish static methods.
Your approach seems a bit flawed to me, but you can check class attributes:
(in Python 2.7):
>>> type(A.f)
<type 'instancemethod'>
>>> type(A.g)
<type 'function'>
or instance attributes in Python 3.x
>>> a = A()
>>> type(a.f)
<type 'method'>
>>> type(a.g)
<type 'function'>
To supplement the answers here, in Python 3 the best way is like so:
import inspect
class Test:
#staticmethod
def test(): pass
isstatic = isinstance(inspect.getattr_static(Test, "test"), staticmethod)
We use getattr_static rather than getattr, since getattr will retrieve the bound method or function, not the staticmethod class object. You can do a similar check for classmethod types and property's (e.g. attributes defined using the #property decorator)
Note that even though it is a staticmethod, don't assume it was defined inside the class. The method source may have originated from another class. To get the true source, you can look at the underlying function's qualified name and module. For example:
class A:
#staticmethod:
def test(): pass
class B: pass
B.test = inspect.getattr_static(A, "test")
print("true source: ", B.test.__qualname__)
Technically, any method can be used as "static" methods, so long as they are called on the class itself, so just keep that in mind. For example, this will work perfectly fine:
class Test:
def test():
print("works!")
Test.test()
That example will not work with instances of Test, since the method will be bound to the instance and called as Test.test(self) instead.
Instance and class methods can be used as static methods as well in some cases, so long as the first arg is handled properly.
class Test:
def test(self):
print("works!")
Test.test(None)
Perhaps another rare case is a staticmethod that is also bound to a class or instance. For example:
class Test:
#classmethod
def test(cls): pass
Test.static_test = staticmethod(Test.test)
Though technically it is a staticmethod, it is really behaving like a classmethod. So in your introspection, you may consider checking the __self__ (recursively on __func__) to see if the method is bound to a class or instance.
I happens to have a module to solve this. And it's Python2/3 compatible solution. And it allows to test with method inherit from parent class.
Plus, this module can also test:
regular attribute
property style method
regular method
staticmethod
classmethod
For example:
class Base(object):
attribute = "attribute"
#property
def property_method(self):
return "property_method"
def regular_method(self):
return "regular_method"
#staticmethod
def static_method():
return "static_method"
#classmethod
def class_method(cls):
return "class_method"
class MyClass(Base):
pass
Here's the solution for staticmethod only. But I recommend to use the module posted here.
import inspect
def is_static_method(klass, attr, value=None):
"""Test if a value of a class is static method.
example::
class MyClass(object):
#staticmethod
def method():
...
:param klass: the class
:param attr: attribute name
:param value: attribute value
"""
if value is None:
value = getattr(klass, attr)
assert getattr(klass, attr) == value
for cls in inspect.getmro(klass):
if inspect.isroutine(value):
if attr in cls.__dict__:
bound_value = cls.__dict__[attr]
if isinstance(bound_value, staticmethod):
return True
return False
Why bother? You can just call g like you call f:
a = A()
a.f()
a.g()
I've seen a class in python which does something of this kind:
obj = Class( name = "somename" )
obj.somename = something
Namely the class initialisation created a member called as the argument string.
I cannot manage to reproduce this behaviour. Any ideas?
I managed to do something similar using globals()["name"] = value. But in this case the created object is son of the module not of the "Class" object. And it's callable as module.somename instead of obj.somename.
You can easily create a dynamically named member by using setattr:
>>> class Foo(object):
... def __init__(self, name):
... setattr(self, name, 42)
...
>>> f = Foo('bar')
>>> f.bar
42
>>> f.bar = 'hello'
>>> f.bar
'hello'
Note however, that just setting any attribute on an instance of a class is possible for any regular class (that doesn't define __slots__):
>>> class Qux(object):
... pass
...
>>> q = Qux()
>>> q.foobar = 'hello'
>>> q.foobar
'hello'
You can either create a dynamically named fixed value property like this:
class MyClass():
def __init__(self, attr):
self.__dict__[attr] = 'some_value'
Or create as many properties as the calling function wants:
class MyClass():
def __init__(self, *argv, **kwargs):
for key,value in kwargs.items():
self.__dict__[key] = value
>>> def hehe():
... return "spam"
...
>>> repr(hehe)
'<function hehe at 0x7fe5624e29b0>'
I want to have:
>>> repr(hehe)
'hehe function created by awesome programmer'
How do I do that? Putting __repr__ inside hehe function does not work.
EDIT:
In case you guys are wondering why I want to do this:
>>> defaultdict(hehe)
defaultdict(<function hehe at 0x7f0e0e252280>, {})
I just don't like the way it shows here.
No, you cannot change the representation of a function object; if you wanted to add documentation, you'd add a docstring:
def foo():
"""Frob the bar baz"""
and access that with help(foo) or print foo.__doc__.
You can create a callable object with a custom __repr__, which acts just like a function:
class MyCallable(object):
def __call__(self):
return "spam"
def __repr__(self):
return 'hehe function created by awesome programmer'
Demo:
>>> class MyCallable(object):
... def __call__(self):
... return "spam"
... def __repr__(self):
... return 'hehe function created by awesome programmer'
...
>>> hehe = MyCallable()
>>> hehe
hehe function created by awesome programmer
>>> hehe()
'spam'
Usually, when you want to change something about the function, say function signature, function behavior or function attributes, you should consider using a decorator. So here is how you might implement what you want:
class change_repr(object):
def __init__(self, functor):
self.functor = functor
# lets copy some key attributes from the original function
self.__name__ = functor.__name__
self.__doc__ = functor.__doc__
def __call__(self, *args, **kwargs):
return self.functor(*args, **kwargs)
def __repr__(self):
return '<function %s created by ...>' % self.functor.__name__
#change_repr
def f():
return 'spam'
print f() # spam
print repr(f) # <function hehe created by ...>
Note, that you can only use class based decorator, since you need to override __repr__ method, which you can't do with a function object.
Not directly the answer to your question, but perhaps you really want a docstring?
>>> def hehe():
... '''hehe function created by awesome programmer'''
... return 'spam'
...
>>> help(hehe)
Help on function hehe in module __main__:
hehe()
hehe function created by awesome programmer
Here's a slightly more flexible version of what's in Alexander Zhukov's answer:
def representation(repr_text):
class Decorator(object):
def __init__(self, functor):
self.functor = functor
def __call__(self, *args, **kwargs):
return self.functor(*args, **kwargs)
def __repr__(self):
return (repr_text % self.functor.__name__ if '%' in repr_text
else repr_text)
return Decorator
from collections import defaultdict
#representation('<function %s created by awesome programmer>')
def f():
return list
dd = defaultdict(f)
print repr(dd)
Output:
defaultdict(<function f created by awesome programmer>, {})
Sincerepresentation()returns a decorator, if you wanted the same boilerplate on several functions you could do something like this:
myrepr = representation('<function %s created by awesome programmer>')
#myrepr
def f():
...
#myrepr
def g():
...
etc
I was under the impression python string formatting using .format() would correctly use properties, instead I get the default behaviour of an object being string-formatted:
>>> def get(): return "Blah"
>>> a = property(get)
>>> "{a}!".format(a=a)
'<property object at 0x221df18>!'
Is this the intended behaviour, and if so what's a good way to implement a special behaviour for properties (eg, the above test would return "Blah!" instead)?
property objects are descriptors. As such, they don't have any special abilities unless accessed through a class.
something like:
class Foo(object):
#property
def blah(self):
return "Cheddar Cheese!"
a = Foo()
print('{a.blah}'.format(a=a))
should work. (You'll see Cheddar Cheese! printed)
Yes, this is basically the same as if you just did:
>>> def get(): return "Blah"
>>> a = property(get)
>>> print a
If you want "Blah" just call the function:
>>> def get(): return "Blah"
>>> a = property(get)
>>> "{a}!".format(a=a.fget())
Python properties do interop well with .format(). Consider the following example:
>>> class Example(object):
... def __init__(self):
... self._x = 'Blah'
... def getx(self): return self._x
... def setx(self, value): self._x = value
... def delx(self): del self._x
... x = property(getx,setx,delx, "I'm the 'x' property.")
...
>>>
>>> ex = Example()
>>> ex.x
'Blah'
>>> print(ex.x)
'Blah'
>>> "{x.x}!".format(x=ex)
'Blah!'
I believe your problem stems from your property not being part of a class. How are you actually using properties that they aren't working with .format()?
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