Calling a method of a class, the classname is a variable - python

I came up with this solution. But this looks too complicated. There must be a better and easier way. And second : is there a way to dynamically import the class ?
class_name = "my_class_name" # located in the module : my_class_name.py
import my_class_name from my_class_name
my_class = globals()[class_name]
object = my_class()
func = getattr(my_class,"my_method")
func(object, parms) # and finally calling the method with some parms

Take a look at the __import__ built-in function. It does exactly what you expect it to do.
Edit: as promised, here's an example. Not a very good one, I just kinda got bad news and my head is elsewhere, so you'd probably write a smarter one with more practical application for your context. At least, it illustrates the point.
>>> def getMethod(module, cls, method):
... return getattr(getattr(__import__(module), cls), method)
...
>>> getMethod('sys', 'stdin', 'write')
<built-in method write of file object at 0x7fcd518fa0c0>
Edit 2: here's a smarter one.
>>> def getMethod(path):
... names = path.split('.')
... return reduce(getattr, names[1:], __import__(names[0]))
...
>>> getMethod('sys.stdin.write')
<built-in method write of file object at 0x7fdc7e0ca0c0>
Are you still around?

Related

Using self in python, outside of a class

I am a bit unsure how to use self outside of a class. A lot of built in methods in python use self as a parameter and there is no need for you to declare the class; For example, you can use the string.upper() command to capitalize each letter without needing to tell python which class to use. In case I'm not explaining myself well, I have included what my code looks like below.
def ispalendrome(self): return self == self[::-1]
largestProd = 999**2
largest5Palendromes = []
while len(largest5Palendromes) <= 5:
if str(largestProd).ispalendrome(): largest5Palendromes.append(largestProd)
largestProd -= 1
print largest5Palendromes
Note: I understand there are other ways of accomplishing this task, but I would like to know if this is possible. TYVM.
using https://github.com/clarete/forbiddenfruit
from forbiddenfruit import curse
def ispalendrome(self): #note that self is really just a variable name ... it doent have to be named self
return self == self[::-1]
curse(str, "ispalendrome",ispalendrome)
"hello".ispalendrome()
note that just because you can does not mean its a good idea
alternatively it is much better to just do
def ispalendrome(a_string):
return a_string == a_string[::-1]
ispalendrome("hello")
It feels like you want to monkey patch a method onto this. If so, then welcome to the dark side young one. Let us begin the cursed ritual. In essence you want to monkey patch. All we need is a little monkey blood. Just kidding. We need type.MethodType. But note, that you cannot monkey patch stdlib types:
>>> from types import MethodType
>>> def palindrome(self): return self == self[::-1]
...
>>> str.palindrome = MethodType(palindrome, str)
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: can't set attributes of built-in/extension type 'str'
But that won't stop you from causing havoc in other classes:
>>> class String(object):
... def __init__(self, done):
... self.done = done
...
...
...
>>> s = String("stanley yelnats")
>>> def palindrome(self): return self.done[::-1]
>>> s.palindrome = MethodType(palindrome, s)
>>> s.palindrome()
'stanley yelnats'
You see how easy that was? But we're just getting started. This is just a mere instance lets kill a class now shall we? The next part will get you laughing maniacally:
>>> from types import DynamicClassAttribute
>>> class String(object):
... def __init__(self, done):
... self.done = done
...
...
...
>>> s = String("cheese")
>>> def palindrome(self): return self.done[::-1];
...
>>> String.palindrome = DynamicClassAttribute(palindrome)
>>> s.palindrome
'eseehc'
After this, if you do not feel evil. Then you must come over to my evil lair, where I shall show you more evil tricks and share cookies.
Self has no special meaning - it is just a variable name. Its use in classes is merely conventional (so it may be confusing to use it elsewhere).
You can, however, set the properties of a class after-the-fact, and these could be class methods or instance methods (the latter with "self" by convention). This will NOT work with the built-in classes like str, though [edit: so you'd have to "curse" or subclass, see other answer]
In
def ispalendrome(self)
there's no need to name the parameter self (indeed, it's a bit misleading), as this isn't an instance method. I would call it s (for string):
def is_palindrome(s):
What you may be referring to is the use of bound methods on the class, where:
an_instance = TheClass()
an_instance.instance_method() # self is passed implicitly
is equivalent to:
an_instance = TheClass()
TheClass.instance_method(an_instance) # self is passed explicitly
In this particular case, for example:
>>> "foo".upper()
'FOO'
>>> str.upper("foo")
'FOO'
In Python the first argument to a class method is the object instance itself, by convention it is called self. You should prevent using self for other purposes.
To explain it more detailed:
If you have a class
class A(object):
def __init__(self):
self.b = 1
and you make an instance of it:
a = A()
this calls the init method and the parameter self if filled with a fresh object. Then self.b = 1 is called and add the attribute b to the new object. This object is then going to become knows as a.
"self" is the name of the first parameter to a function - like any parameter, it has no meaning outside of that function. What it corresponds to is the object on which that function is called.

How do Python tell “this is called as a function”?

A callable object is supposed to be so by defining __call__. A class is supposed to be an object… or at least with some exceptions. This exception is what I'm failing to formally clarify, thus this question posted here.
Let A be a simple class:
class A(object):
def call(*args):
return "In `call`"
def __call__(*args):
return "In `__call__`"
The first function is purposely named “call”, to make clear the purpose is the comparison with the other.
Let's instantiate it and forget about the expression it implies:
a = A() # Think of it as `a = magic` and forget about `A()`
Now what's worth:
print(A.call())
print(a.call())
print(A())
print(a())
Result in:
>>> In `call`
>>> In `call`
>>> <__main__.A object at 0xNNNNNNNN>
>>> In `__call__`
The output (third statement not running __call__) does not come as a surprise, but when I think every where it is said “Python class are objects”…
This, more explicit, however run __call__
print(A.__call__())
print(a.__call__())
>>> “In `__call__`”
>>> “In `__call__`”
All of this is just to show how finally A() may looks strange.
There are exception in Python rules, but the documentation about “object.call” does not say a lot about __call__… not more than that:
3.3.5. Emulating callable objects
object.__call__(self[, args...])
Called when the instance is “called” as a function; […]
But how do Python tell “it's called as a function” and honour or not the object.__call__ rule?
This could be a matter of type, but even type has object as its base class.
Where can I learn more (and formally) about it?
By the way, is there any difference here between Python 2 and Python 3?
----- %< ----- edit ----- >% -----
Conclusions and other experiments after one answer and one comment
Update #1
After #Veedrac's answer and #chepner's comment, I came to this other test, which complete the comments from both:
class M(type):
def __call__(*args):
return "In `M.__call__`"
class A(object, metaclass=M):
def call(*args):
return "In `call`"
def __call__(*args):
return "In `A.__call__`"
print(A())
The result is:
>>> In `M.__call__`
So it seems that's the meta‑class which drives the “call” operations. If I understand correctly, the meta‑class does not matter only with class, but also with classes instances.
Update #2
Another relevant test, which shows this is not an attribute of the object which matters, but an attribute of the type of the object:
class A(object):
def __call__(*args):
return "In `A.__call__`"
def call2(*args):
return "In `call2`"
a = A()
print(a())
As expected, it prints:
>>> In `A.__call__`
Now this:
a.__call__ = call2
print(a())
It prints:
>>> In `A.__call__`
The same a before the attribute was assigned. It does not print In call2, it's still In A.__call__. That's important to note and also explain why that's the __call__ of the meta‑class which was invoked (keep in mind the meta‑class is the type of the class object). The __call__ used to call as function, is not from the object, it's from its type.
x(*args, **kwargs) is the same as type(x).__call__(x, *args, **kwargs).
So you have
>>> type(A).__call__(A)
<__main__.A object at 0x7f4d88245b50>
and it all makes sense.
chepner points out in the comments that type(A) == type. This is kind-of wierd, because type(A)(A) just gives type again! But remember that we're instead using type(A).__call__(A) which is not the same.
So this resolves to type.__call__(A). This is the constructor function for classes, which builds the data-structures and does all the construction magic.
The same is true of most dunder (double underscore) methods, such as __eq__. This is partially an optimisation in those cases.

Python: dereferencing weakproxy

Is there any way to get the original object from a weakproxy pointed to it? eg is there the inverse to weakref.proxy()?
A simplified example(python2.7):
import weakref
class C(object):
def __init__(self, other):
self.other = weakref.proxy(other)
class Other(object):
pass
others = [Other() for i in xrange(3)]
my_list = [C(others[i % len(others)]) for i in xrange(10)]
I need to get the list of unique other members from my_list. The way I prefer for such tasks
is to use set:
unique_others = {x.other for x in my_list}
Unfortunately this throws TypeError: unhashable type: 'weakproxy'
I have managed to solve the specific problem in an imperative way(slow and dirty):
unique_others = []
for x in my_list:
if x.other in unique_others:
continue
unique_others.append(x.other)
but the general problem noted in the caption is still active.
What if I have only my_list under control and others are burried in some lib and someone may delete them at any time, and I want to prevent the deletion by collecting nonweak refs in a list?
Or I may want to get the repr() of the object itself, not <weakproxy at xx to Other at xx>
I guess there should be something like weakref.unproxy I'm not aware about.
I know this is an old question but I was looking for an answer recently and came up with something. Like others said, there is no documented way to do it and looking at the implementation of weakproxy type confirms that there is no standard way to achieve this.
My solution uses the fact that all Python objects have a set of standard methods (like __repr__) and that bound method objects contain a reference to the instance (in __self__ attribute).
Therefore, by dereferencing the proxy to get the method object, we can get a strong reference to the proxied object from the method object.
Example:
>>> def func():
... pass
...
>>> weakfunc = weakref.proxy(func)
>>> f = weakfunc.__repr__.__self__
>>> f is func
True
Another nice thing is that it will work for strong references as well:
>>> func.__repr__.__self__ is func
True
So there's no need for type checks if either a proxy or a strong reference could be expected.
Edit:
I just noticed that this doesn't work for proxies of classes. This is not universal then.
Basically there is something like weakref.unproxy, but it's just named weakref.ref(x)().
The proxy object is only there for delegation and the implementation is rather shaky...
The == function doesn't work as you would expect it:
>>> weakref.proxy(object) == object
False
>>> weakref.proxy(object) == weakref.proxy(object)
True
>>> weakref.proxy(object).__eq__(object)
True
However, I see that you don't want to call weakref.ref objects all the time. A good working proxy with dereference support would be nice.
But at the moment, this is just not possible. If you look into python builtin source code you see, that you need something like PyWeakref_GetObject, but there is just no call to this method at all (And: it raises a PyErr_BadInternalCall if the argument is wrong, so it seems to be an internal function). PyWeakref_GET_OBJECT is used much more, but there is no method in weakref.py that could be able to do that.
So, sorry to disappoint you, but you weakref.proxy is just not what most people would want for their use cases. You can however make your own proxy implementation. It isn't to hard. Just use weakref.ref internally and override __getattr__, __repr__, etc.
On a little sidenote on how PyCharm is able to produce the normal repr output (Because you mentioned that in a comment):
>>> class A(): pass
>>> a = A()
>>> weakref.proxy(a)
<weakproxy at 0x7fcf7885d470 to A at 0x1410990>
>>> weakref.proxy(a).__repr__()
'<__main__.A object at 0x1410990>'
>>> type( weakref.proxy(a))
<type 'weakproxy'>
As you can see, calling the original __repr__ can really help!
weakref.ref is hashable whereas weakref.proxy is not. The API doesn't say anything about how you actually can get a handle on the object a proxy points to. with weakref, it's easy, you can just call it. As such, you can roll your own proxy-like class...Here's a very basic attemp:
import weakref
class C(object):
def __init__(self,obj):
self.object=weakref.ref(obj)
def __getattr__(self,key):
if(key == "object"): return object.__getattr__(self,"object")
elif(key == "__init__"): return object.__getattr__(self,"__init__")
else:
obj=object.__getattr__(self,"object")() #Dereference the weakref
return getattr(obj,key)
class Other(object):
pass
others = [Other() for i in range(3)]
my_list = [C(others[i % len(others)]) for i in range(10)]
unique_list = {x.object for x in my_list}
Of course, now unique_list contains refs, not proxys which is fundamentally different...
I know that this is an old question, but I've been bitten by it (so, there's no real 'unproxy' in the standard library) and wanted to share my solution...
The way I solved it to get the real instance was just creating a property which returned it (although I suggest using weakref.ref instead of a weakref.proxy as code should really check if it's still alive before accessing it instead of having to remember to catch an exception whenever any attribute is accessed).
Anyways, if you still must use a proxy, the code to get the real instance is:
import weakref
class MyClass(object):
#property
def real_self(self):
return self
instance = MyClass()
proxied = weakref.proxy(instance)
assert proxied.real_self is instance

Attribute added with setattr not showing up in help()

I've got a class that I'm adding a help-function to with setattr. The function is a properly created instancemethod and works like a charm.
import new
def add_helpfunc(obj):
def helpfunc(self):
"""Nice readable docstring"""
#code
setattr(obj, "helpfunc",
new.instancemethod(helpfunc, obj, type(obj)))
However, when calling help on the object instance, the new method is not listed as a member of the object. I thought help (i.e. pydoc) used dir(), but dir() works and not help().
What do I have to do to get the help information updated?
I there a specific reason you do it the complicate way? Why not just doing it like this:
def add_helpfunc(obj):
def helpfunc(self):
"""Nice readable docstring"""
#code
obj.helpfunc = helpfunc
Adding the method this way also fixes your help-problem if I am not wrong...
Example:
>>> class A:
... pass
...
>>> add_helpfunc(A)
>>> help(A.helpfunc)
Help on method helpfunc in module __main__:
helpfunc(self) unbound __main__.A method
Nice readable docstring
>>> help(A().helpfunc)
Help on method helpfunc in module __main__:
helpfunc(self) method of __main__.A instance
Nice readable docstring

Using class/static methods as default parameter values within methods of the same class

I'd like to do something like this:
class SillyWalk(object):
#staticmethod
def is_silly_enough(walk):
return (False, "It's never silly enough")
def walk(self, appraisal_method=is_silly_enough):
self.do_stuff()
(was_good_enough, reason) = appraisal_method(self)
if not was_good_enough:
self.execute_self_modifying_code(reason)
return appraisal_method
def do_stuff(self):
pass
def execute_self_modifying_code(self, problem):
from __future__ import deepjuju
deepjuju.kiss_booboo_better(self, problem)
with the idea being that someone can do
>>> silly_walk = SillyWalk()
>>> appraise = walk()
>>> is_good_walk = appraise(silly_walk)
and also get some magical machine learning happening; this last bit is not of particular interest to me, it was just the first thing that occurred to me as a way to exemplify the use of the static method in both an in-function context and from the caller's perspective.
Anyway, this doesn't work, because is_silly_enough is not actually a function: it is an object whose __get__ method will return the original is_silly_enough function. This means that it only works in the "normal" way when it's referenced as an object attribute. The object in question is created by the staticmethod() function that the decorator puts in between SillyWalk's is_silly_enough attribute and the function that's originally defined with that name.
This means that in order to use the default value of appraisal_method from within either SillyWalk.walk or its caller, we have to either
call appraisal_method.__get__(instance, owner)(...) instead of just calling appraisal_method(...)
or assign it as the attribute of some object, then reference that object property as a method that we call as we would call appraisal_method.
Given that neither of these solutions seem particularly Pythonic™, I'm wondering if there is perhaps a better way to get this sort of functionality. I essentially want a way to specify that a method should, by default, use a particular class or static method defined within the scope of the same class to carry out some portion of its daily routine.
I'd prefer not to use None, because I'd like to allow None to convey the message that that particular function should not be called. I guess I could use some other value, like False or NotImplemented, but it seems a) hackety b) annoying to have to write an extra couple of lines of code, as well as otherwise-redundant documentation, for something that seems like it could be expressed quite succinctly as a default parameter.
What's the best way to do this?
Maybe all you need is to use the function (and not the method) in the first place?
class SillyWalk(object):
def is_silly_enough(walk):
return (False, "It's never silly enough")
def walk(self, appraisal_function=is_silly_enough):
self.do_stuff()
(was_good_enough, reason) = appraisal_function(self)
if not was_good_enough:
self.execute_self_modifying_code(reason)
return appraisal_function
def do_stuff(self):
pass
def execute_self_modifying_code(self, problem):
deepjuju.kiss_booboo_better(self, problem)
Note that the default for appraisal_function will now be a function and not a method, even though is_silly_enough will be bound as a class method once the class is created (at the end of the code).
This means that
>>> SillyWalk.is_silly_enough
<unbound method SillyWalk.is_silly_enough>
but
>>> SillyWalk.walk.im_func.func_defaults[0] # the default argument to .walk
<function is_silly_enough at 0x0000000002212048>
And you can call is_silly_enough with a walk argument, or call a walk instance with .is_silly_enough().
If you really wanted is_silly_enough to be a static method, you could always add
is_silly_enough = staticmethod(is_silly_enough)
anywhere after the definition of walk.
I ended up writing an (un)wrapper function, to be used within function definition headers, eg
def walk(self, appraisal_method=unstaticmethod(is_silly_enough)):
This actually seems to work, at least it makes my doctests that break without it pass.
Here it is:
def unstaticmethod(static):
"""Retrieve the original function from a `staticmethod` object.
This is intended for use in binding class method default values
to static methods of the same class.
For example:
>>> class C(object):
... #staticmethod
... def s(*args, **kwargs):
... return (args, kwargs)
... def m(self, args=[], kwargs={}, f=unstaticmethod(s)):
... return f(*args, **kwargs)
>>> o = C()
>>> o.s(1, 2, 3)
((1, 2, 3), {})
>>> o.m((1, 2, 3))
((1, 2, 3), {})
"""
# TODO: Technically we should be passing the actual class of the owner
# instead of `object`, but
# I don't know if there's a way to get that info dynamically,
# since the class is not actually declared
# when this function is called during class method definition.
# I need to figure out if passing `object` instead
# is going to be an issue.
return static.__get__(None, object)
update:
I wrote doctests for the unstaticmethod function itself; they pass too. I'm still not totally sure that this is an actual smart thing to do, but it does seem to work.
Not sure if I get exactly what you're after, but would it be cleaner to use getattr?
>>> class SillyWalk(object):
#staticmethod
def ise(walk):
return (False, "boo")
def walk(self, am="ise"):
wge, r = getattr(self, am)(self)
print wge, r
>>> sw = SillyWalk()
>>> sw.walk("ise")
False boo

Categories