class Foo(object):
def tick(self):
print("something")
class Bar(object):
def __init__(self):
self.foo = Foo()
def tick(self):
#Here's what I do....
self.foo.tick()
#here's what my goal would be
self.foo()
b = Bar()
b.tick()
That's essentially my goal. From what I've gathered I could change the tick function to __call__ and that would allow me to do what I wanted. A couple of the other answers said that this would make a new instance of the object, does that mean that it would use self.foo's memory? or would it make a whole new object, newly instanced? or make a copy of self.foo?
Also a couple of drawbacks to this which may or may not manifest themselves come to mind. For a particular part of my program, I check to see if the object has a __call__ to determine if the argument I'm passing is a function or a variable, and I don't really think I would want to allow that to be called (even though, I suppose the class technically would be a function at that point.) Is there any way to distinguish between a function and a callable class?
Is there anything else that would make doing this undesirable (and is it a pythonic way to work?)? My next thought had been that given that other variable prefixed with __ cant be used outside their class, but that doesnt seem to be the case here.
Changing tick(self) to __call__(self) is the correct solution.
This has nothing to do with memory allocation. All __call__ signifies is the function which Python calls when you use (for an object foo) the syntax foo().
For your later question: to check whether something is an object, use isinstance or issubclass (possibly with the object class). And in my mind this answer is better than the accepted one for the "How do I determine if something is a function?" question you've probably seen.
To make a class instance callable, all you need to do is implement a __call__ method. Then, to call the __call__ method, you just do: instance(arg1,arg2,...) -- in other words, you call the instance the same way you would call a function.
Note that you can alias __call__ with some other method defined on the class if you want:
>>> class Foo(object):
... def tick(self):
... print ("something")
... __call__ = tick
...
>>> a = Foo()
>>> a()
something
>>> a.tick()
something
Related
If someone writes a class in python, and fails to specify their own __repr__() method, then a default one is provided for them. However, suppose we want to write a function which has the same, or similar, behavior to the default __repr__(). However, we want this function to have the behavior of the default __repr__() method even if the actual __repr__() for the class was overloaded. That is, suppose we want to write a function which has the same behavior as a default __repr__() regardless of whether someone overloaded the __repr__() method or not. How might we do it?
class DemoClass:
def __init__(self):
self.var = 4
def __repr__(self):
return str(self.var)
def true_repr(x):
# [magic happens here]
s = "I'm not implemented yet"
return s
obj = DemoClass()
print(obj.__repr__())
print(true_repr(obj))
Desired Output:
print(obj.__repr__()) prints 4, but print(true_repr(obj)) prints something like:
<__main__.DemoClass object at 0x0000000009F26588>
You can use object.__repr__(obj). This works because the default repr behavior is defined in object.__repr__.
Note, the best answer is probably just to use object.__repr__ directly, as the others have pointed out. But one could implement that same functionality roughly as:
>>> def true_repr(x):
... type_ = type(x)
... module = type_.__module__
... qualname = type_.__qualname__
... return f"<{module}.{qualname} object at {hex(id(x))}>"
...
So....
>>> A()
hahahahaha
>>> true_repr(A())
'<__main__.A object at 0x106549208>'
>>>
Typically we can use object.__repr__ for that, but this will to the "object repr for every item, so:
>>> object.__repr__(4)
'<int object at 0xa6dd20>'
Since an int is an object, but with the __repr__ overriden.
If you want to go up one level of overwriting, we can use super(..):
>>> super(type(4), 4).__repr__() # going up one level
'<int object at 0xa6dd20>'
For an int that thus again means that we will print <int object at ...>, but if we would for instance subclass the int, then it would use the __repr__ of int again, like:
class special_int(int):
def __repr__(self):
return 'Special int'
Then it will look like:
>>> s = special_int(4)
>>> super(type(s), s).__repr__()
'4'
What we here do is creating a proxy object with super(..). Super will walk the method resolution order (MRO) of the object and will try to find the first function (from a superclass of s) that has overriden the function. If we use single inheritance, that is the closest parent that overrides the function, but if it there is some multiple inheritance involved, then this is more tricky. We thus select the __repr__ of that parent, and call that function.
This is also a rather weird application of super since usually the class (here type(s)) is a fixed one, and does not depend on the type of s itself, since otherwise multiple such super(..) calls would result in an infinite loop.
But usually it is a bad idea to break overriding anyway. The reason a programmer overrides a function is to change the behavior. Not respecting this can of course sometimes result into some useful functions, but frequently it will result in the fact that the code contracts are no longer satisfied. For example if a programmer overrides __eq__, he/she will also override __hash__, if you use the hash of another class, and the real __eq__, then things will start breaking.
Calling magic function directly is also frequently seen as an antipattern, so you better avoid that as well.
I have a function that generally accepts lists, but on occasions needs to accept functions as well. There were several ways of dealing with this, but it would have been very very useful to be able to do len(foo) for a given function foo.
In the end, instead of passing in functions, I passed in callable classes that had a __len__ function defined. But it got me thinking, since in python everything is an object, and functions can have attributes etc. just as a curiosity...
Question
Is there any way to give a function a len? A quick google didn't bring up anything.
My attempt
def foo():
return True
def my_len(self):
return 5
foo.__len__ = my_len
len(foo)
Adding __len__ to an object is not working (see this link added by Aran-Fey why). A function is just an object defining a __call__ method. You can define a class like this:
class Foo:
def __call__(self):
return True
def __len__(self):
return 5
Using it:
>>> foo=Foo()
>>> foo()
True
>>> len(foo)
5
It is possible to create a function which is having a length, but you should consider the use case. Python gives you a lot of power, but not everything what's possible is actually a good idea.
If I have the following class.
class Foo:
#staticmethod
def _bar():
# do something
print "static method"
def instancemethod(self):
Foo._bar() # method 1
self._bar() # method 2
In this case, is method 1 a preferred way of calling staticmethod _bar() or method 2 in the Python world?
Write the code that expresses what you want to do. If you want to call this method right here:
class Foo:
#staticmethod
def _bar(): # <-- this one
# do something
print "static method"
then specify that particular method:
Foo._bar()
If you want to call whatever self._bar resolves to, meaning you've actually decided that it makes sense to override it and made sure your code still behaves sensibly when that method is overridden, then specify self._bar:
self._bar()
Most likely, this method isn't designed to be overridden, and the code that uses it isn't designed to anticipate overriding it, so you probably want Foo._bar().
I want to use new.instancemethod to assign a function (aFunction) from one class (A) to an instance of another class (B). I'm not sure how I can get aFunction to allow itself to be applied to an instance of B - currently I am getting an error because aFunction is expecting to be executed on an instance of A.
[Note: I can't cast instance to A using the __class__ attribute as the class I'm using (B in my example) doesn't support typecasting]
import new
class A(object):
def aFunction(self):
pass
#Class which doesn't support typecasting
class B(object):
pass
b = B()
b.aFunction = new.instancemethod(A.aFunction, b, B.__class__)
b.aFunction()
This is the error:
TypeError: unbound method aFunction() must be called with A instance as first argument (got B instance instead)
new.instancemethod takes a function. A.aFunction is an unbound method. That's not the same thing. (You may want to try adding a bunch of print statements to display all of the things involved—A.aFunction(), A().aFunction, etc.—and their types, to help understanding.)
I'm assuming you don't how descriptors work. If you don't want to learn all of the gory details, what's actually going on is that your declaration of aFunction within a class definition creates a non-data descriptor out of the function. This is a magic thing that means that, depending on how you access it, you get an unbound method (A.aFunction) or a bound method (A().aFunction).
If you modify aFunction to be a #staticmethod, this will actually work, because for a static method both A.aFunction and A().aFunction are just functions. (I'm not sure that's guaranteed to be true by the standard, but it's hard to see how else anyone would ever implement it.) But if you want "aFunction to allow itself to be applied to an instance of B", a static method won't help you.
If you actually want to get the underlying function, there are a number of ways to do it; I think this is the clearest as far as helping you understand how descriptors works:
f = object.__getattribute__(A, 'aFunction')
On the other hand, the simplest is probably:
f = A.aFunction.im_func
Then, calling new.instancemethod is how you turn that function into a descriptor that can be called as a regular method for instances of class B:
b.aFunction = new.instancemethod(f, b, B)
Printing out a bunch of data makes things a lot clearer:
import new
class A(object):
def aFunction(self):
print self, type(self), type(A)
#Class which doesn't support typecasting
class B(object):
pass
print A.aFunction, type(A.aFunction)
print A().aFunction, type(A().aFunction)
print A.aFunction.im_func, type(A.aFunction.im_func)
print A().aFunction.im_func, type(A().aFunction.im_func)
A.aFunction(A())
A().aFunction()
f = object.__getattribute__(A, 'aFunction')
b = B()
b.aFunction = new.instancemethod(f, b, B)
b.aFunction()
You'll see something like this:
<unbound method A.aFunction> <type 'instancemethod'>
<bound method A.aFunction of <__main__.A object at 0x108b82d10>> <type 'instancemethod'>
<function aFunction at 0x108b62a28> <type 'function'>
<function aFunction at 0x108b62a28> <type 'function'>
<__main__.A object at 0x108b82d10> <class '__main__.A'> <type 'type'>
<__main__.A object at 0x108b82d10> <class '__main__.A'> <type 'type'>
<__main__.B object at 0x108b82d10> <class '__main__.B'> <type 'type'>
The only thing this doesn't show is the magic that creates the bound and unbound methods. For that, you need to look into A.aFunction.im_func.__get__, and at that point you're better off reading the descriptor howto than trying to dig it apart yourself.
One last thing: As brandizzi pointed out, this is something you almost never want to do. Alternatives include: Write aFunction as a free function instead of a method, so you just call b.aFunction(); factor out a function that does the real work, and have A.aFunction and B.aFunction just call it; have B aggregate an A and forward to it; etc.
I already posted an answer to the question you asked. But you shouldn't have had to get down to the level of having to understand new.instancemethod to solve your problem. The only reason that happened is because you asked the wrong question. Let's look at what you should have asked, and why.
In PySide.QtGui, I want the list widget items to have methods to set the font and colors, and they don't seem to.
This is what you really want. There may well be an easy way to do this. And if so, that's the answer you want. Also, by starting off with this, you avoid all the comments about "What do you actually want to do?" or "I doubt this is appropriate for whatever you're trying to do" (which often come with downvotes—or, more importantly, with potential answerers just ignoring your question).
Of course I could just write a function that takes a QListWidgetItem and call that function, instead of making it a method, but that won't work for me because __.
I assume there's a reason that won't work for you. But I can't really think of a good one. Whatever line of code said this:
item.setColor(color)
would instead say this:
setItemColor(item, color)
Very simple.
Even if you need to, e.g., pass around a color-setting delegate with the item bound into it, that's almost as easy with a function as with a method. Instead of this:
delegate = item.setColor
it's:
delegate = lambda color: setItemColor(item, color)
So, if there is a good reason you need this to be a method, that's something you really should explain. And if you're lucky, it'll turn out you were wrong, and there's a much simpler way to do what you want than what you were trying.
The obvious way to do this would be to get PySide to let me specify a class or factory function, so I could write a QListWidgetItem subclass, and every list item I ever deal with would be an instance of that subclass. But I can't find any way to do that.
This seems like something that should be a feature of PySide. So maybe it is, in which case you'd want to know. And if it isn't, and neither you nor any of the commenters or answerers can think of a good reason it would be bad design or hard to implement, you should go file a feature request and it might be in the next version. (Not that this helps you if you need to release code next week against the current version, but it's still worth doing.)
Since I couldn't find a way to do that, I tried to find some way to add my setColor method to the QListWidgetItem class, but couldn't think of anything.
Monkey-patching classes is very simple:
QListWidgetItem.setColor = setItemColor
If you didn't know you could do this, that's fine. If people knew that's what you were trying to do, this would be the first thing they'd suggest. (OK, maybe not many Python programmers know much about monkey-patching, but it's still a lot more than the number who know about descriptors or new.instancemethod.) And again, besides being an answer you'd get faster and with less hassle, it's a better answer.
Even if you did know this, some extension modules won't let you do that. If you tried and it failed, explain what didn't work instead:
PySide wouldn't let me add the method to the class; when I try monkey-patching, __.
Maybe someone knows why it didn't work. If not, at least they know you tried.
So I have to add it to every instance.
Monkey-patching instances looks like this:
myListWidgetItem.setColor = setItemColor
So again, you'd get a quick answer, and a better one.
But maybe you knew that, and tried it, and it didn't work either:
PySide also wouldn't let me add the method to each instance; when I try, __.
So I tried patching out the __class__ of each instance, to make it point to a custom subclass, because that works in PyQt4, but in PySide it __.
This probably won't get you anything useful, because it's just the way PySide works. But it's worth mentioning that you tried.
So, I decided to create that custom subclass, then copy its methods over, like so, but __.
And all the way down here is where you'd put all the stuff you put in your original question. If it really were necessary to solving your problem, the information would be there. But if there were an easy solution, you wouldn't get a bunch of confused answers from people who were just guessing at how new.instancemethod works.
If possible you can make the aFunction unbound by using #staticmethod decorator: -
class A(object):
#staticmethod
def aFunction(B): # Modified to take appropriate parameter..
pass
class B(object):
pass
b = B()
b.aFunction = new.instancemethod(A.aFunction, b, B.__class__)
b.aFunction()
*NOTE: - You need to modify the method to take appropriate parameter..
I'm amazed that none of these answers gives what seems the simplest solution, specifically where you want an existing instance to have a method x replaced by a method x (same name) from another class (e.g. subclass) by being "grafted" on to it.
I had this issue in the very same context, i.e. with PyQt5. Specifically, using a QTreeView class, the problem is that I have subclassed QStandardItem (call it MyItem) for all the tree items involved in the tree structure (first column) and, among other things, adding or removing such an item involves some extra stuff, specifically adding a key to a dictionary or removing the key from this dictionary.
Overriding appendRow (and removeRow, insertRow, takeRow, etc.) presents no problem:
class MyItem( QStandardItem ):
...
def appendRow( self, arg ):
# NB QStandarItem.appendRow can be called either with an individual item
# as "arg", or with a list of items
if isinstance( arg, list ):
for element in arg:
assert isinstance( element, MyItem )
self._on_adding_new_item( element )
elif isinstance( arg, MyItem ):
self._on_adding_new_item( arg )
else:
raise Exception( f'arg {arg}, type {type(arg)}')
super().appendRow( self, arg )
... where _on_adding_new_item is a method which populates the dictionary.
The problem arises when you want to want to add a "level-0" row, i.e. a row the parent of which is the "invisible root" of the QTreeView. Naturally you want the items in this new "level-0" row to cause a dictionary entry to be created for each, but how to get this invisible root item, class QStandardItem, to do this?
I tried overriding the model's method invisibleRootItem() to deliver not super().invisibleRootItem(), but instead a new MyItem. This didn't seem to work, probably because QStandardItemModel.invisibleRootItem() does things behind the scenes, e.g. setting the item's model() method to return the QStandardItemModel.
The solution was quite simple:
class MyModel( QStandardItemModel ):
def __init__( self ):
self.root_item = None
...
...
def invisibleRootItem( self ):
# if this method has already been called we don't need to do our modification
if self.root_item != None:
return self.root_item
self.root_item = super().invisibleRootItem()
# now "graft" the method from MyItem class on to the root item instance
def append_row( row ):
MyItem.appendRow( self.root_item, row )
self.root_item.appendRow = append_row
... this is not quite enough, however: super().appendRow( self, arg ) in MyItem.appendRow will then raise an Exception when called on the root item, because a QStandardItem has no super(). Instead, MyItem.appendRow is changed to this:
def appendRow( self, arg ):
if isinstance( arg, list ):
for element in arg:
assert isinstance( element, MyItem )
self._on_adding_new_item( element )
elif isinstance( arg, MyItem ):
self._on_adding_new_item( arg )
else:
raise Exception( f'arg {arg}, type {type(arg)}')
QStandardItem.appendRow( self, arg )
Thanks Rohit Jain - this is the answer:
import new
class A(object):
#staticmethod
def aFunction(self):
pass
#Class which doesn't support typecasting
class B(object):
pass
b = B()
b.aFunction = new.instancemethod(A.aFunction, b, B.__class__)
b.aFunction()
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