[The code in the original version was badly messed up. Even after I fixed the code, several highly confusing typos remained in the post. I believe I finally fixed all of them too. Profuse apologies.]
The two calls to alias below produce different outputs, because the object associated with the variable my_own_id changes between the two calls:
>>> def my_own_id():
... me = my_own_id
... return id(me)
...
>>> alias = my_own_id
>>> alias()
4301701560
>>> my_own_id = None
>>> alias()
4296513024
What can I assign to me in the definition of my_own_id so that its output remains invariant wrt subsequent re-definitions of the my_own_id variable? (IOW, so that the internal me variable always refers to the same function object?)
(I can get the current frame (with inspect.currentframe()), but it contains only a reference to the current code object, not to the current function.)
P.S. The motivation for this question is only to know Python better.
It seems that referring to my_own_id will look for 'my_own_id' in the global namespace dictionary, so it will always be the name used on function definition. Since that name can be assigned to different values, the value retrieved can also change. If you make me a default argument, you can assign it to the function itself at function definition to keep a reference to the actual function.
You could use this decorator which implicitly passes the original function itself as the first argument.
>>> from functools import wraps
>>> def save_id(func):
#wraps(func)
def wrapper(*args, **kwargs):
return func(func, *args, **kwargs)
return wrapper
>>> #save_id
def my_own_id(me): # me is passed implicitly by save_id
return id(me)
>>> alias = my_own_id
>>> alias()
40775152
>>> my_own_id = 'foo'
>>> alias()
40775152
Indeed, if you rely only on the function name, if that name is overitten in the global variable space (in the module the function was defined), a reference using the name of the function itslef will fail
The easier, more maintanable way is to write a decorator for that, that would provide a nonlocalvariable containing a reference to the function itself.
from functools import wraps
def know_thyself(func):
#wraps(func):
def new_func(*args, **kwargs):
my_own_id = func
return func(*args, **kwargs)
return new_func
And can be used as:
>>> #know_thyself
... def my_own_id():
... me = my_own_id
... return id(me)
...
There is another possible approach, far from being this clean, using frame introspection
and rebuilding a new function re-using the same object code. I had used this on this post
about a self-referential lambda expression in Python:
http://metapython.blogspot.com.br/2010/11/recursive-lambda-functions.html
Well, if you don't mind calling a function (to get the desired function into the global scope), you can wrap the function to protect its definition:
>>> def be_known():
... global my_own_id
... def _my_own_id():
... return id(_my_own_id)
... my_own_id = _my_own_id
...
>>> be_known()
>>> my_own_id()
140685505972568
>>> alias, my_own_id = my_own_id, None
>>> alias()
140685505972568
Note that the protected function must call itself with the nonlocal name, not the global name.
The decorator approach is probably the best one. Here are some more for fun:
Hijack one of the function arguments to provide a static variable.
def fn(fnid=None):
print "My id:", fnid
fn.func_defaults = (id(fn),)
There are a few ways to get the current function here: Python code to get current function into a variable?; most of these involve searching for currentframe.f_code in a variety of places. These work without any modification to the original function.
import inspect
def _this_fn():
try:
frame = inspect.currentframe().f_back
code = frame.f_code
return frame.f_globals[code.co_name]
finally:
del code
del frame
def myfunc(*parms):
print _this_fn()
>>> myfunc(1)
<function myfunc at 0x036265F0>
>>> myfunc
<function myfunc at 0x036265F0>
It's due to scope
>>> def foo():
... x = foo
... print x
...
>>> foo()
<function foo at 0x10836e938>
>>> alias = foo
>>> alias()
<function foo at 0x10836e938>
>>> foo = None
>>> alias()
None
>>> foo = []
>>> alias()
[]
>>> del foo
>>> alias()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in foo
NameError: global name 'foo' is not defined
>>>
Luke had an idea but didn't appear to develop it: use a mutable default parameter to hold the value in the function object. Default parameter values are evaluated only once, when the function is defined, and retain their previous value after that.
>>> def my_own_id(me=[None]):
if not me[0]:
me[0] = my_own_id
return id(me[0])
>>> alias = my_own_id
>>> alias()
40330928
>>> my_own_id = None
>>> alias()
40330928
This requires care on your part to never call the function with a parameter.
Related
I have seen source code where more than one methods are called on an object eg x.y().z() Can someone please explain this to me, does this mean that z() is inside y() or what?
This calls the method y() on object x, then the method z() is called on the result of y() and that entire line is the result of method z().
For example
friendsFavePizzaToping = person.getBestFriend().getFavoritePizzaTopping()
This would result in friendsFavePizzaTopping would be the person's best friend's favorite pizza topping.
Important to note: getBestFriend() must return an object that has the method getFavoritePizzaTopping(). If it does not, an AttributeError will be thrown.
Each method is evaluated in turn, left to right. Consider:
>>> s='HELLO'
>>> s.lower()
'hello'
>>> s='HELLO '
>>> s.lower()
'hello '
>>> s.lower().strip()
'hello'
>>> s.lower().strip().upper()
'HELLO'
>>> s.lower().strip().upper().replace('H', 'h')
'hELLO'
The requirement is that the object to the left in the chain has to have availability of the method on the right. Often that means that the objects are similar types -- or at least share compatible methods or an understood cast.
As an example, consider this class:
class Foo:
def __init__(self, name):
self.name=name
def m1(self):
return Foo(self.name+'=>m1')
def m2(self):
return Foo(self.name+'=>m2')
def __repr__(self):
return '{}: {}'.format(id(self), self.name)
def m3(self):
return .25 # return is no longer a Foo
Notice that as a type of immutable, each return from Foo is a new object (either a new Foo for m1, m2 or a new float). Now try those methods:
>>> foo
4463545376: init
>>> foo.m1()
4463545304: init=>m1
^^^^ different object id
>>> foo
4463545376: init
^^^^ foo still the same because you need to assign it to change
Now assign:
>>> foo=foo.m1().m2()
>>> foo
4464102576: init=>m1=>m2
Now use m3() and it will be a float; not a Foo anymore:
>>> foo=foo.m1().m2().m3()
>>> foo
.25
Now a float -- can't use foo methods anymore:
>>> foo.m1()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'float' object has no attribute 'm1'
But you can use float methods:
>>> foo.as_integer_ratio()
(1, 4)
In the case of:
x.y().z()
You're almost always looking at immutable objects. Mutable objects don't return anything that would HAVE a function like that (for the most part, but I'm simplifying). For instance...
class x:
def __init__(self):
self.y_done = False
self.z_done = False
def y(self):
new_x = x()
new_x.y_done = True
return new_x
def z(self):
new_x = x()
new_x.z_done = True
return new_x
You can see that each of x.y and x.z returns an x object. That object is used to make the consecutive call, e.g. in x.y().z(), x.z is not called on x, but on x.y().
x.y().z() =>
tmp = x.y()
result = tmp.z()
In #dawg's excellent example, he's using strings (which are immutable in Python) whose methods return strings.
string = 'hello'
string.upper() # returns a NEW string with value "HELLO"
string.upper().replace("E","O") # returns a NEW string that's based off "HELLO"
string.upper().replace("E","O") + "W"
# "HOLLOW"
The . "operator" is Python syntax for attribute access. x.y is (nearly) identical to
getattr(x, 'y')
so x.y() is (nearly) identical to
getattr(x, 'y')()
(I say "nearly identical" because it's possible to customize attribute access for a user-defined class. From here on out, I'll assume no such customization is done, and you can assume that x.y is in fact identical to getattr(x, 'y').)
If the thing that x.y() returns has an attribute z such that
foo = getattr(x, 'y')
bar = getattr(foo(), 'z')
is legal, then you can chain the calls together without needing the name foo in the middle:
bar = getattr(getattr(x, 'y')(), 'z')
Converting back to dot notation gives you
bar = getattr(x.y(), 'z')
or simply
bar = x.y().z()
x.y().z() means that the x object has the method y() and the result of x.y() object has the method z() . Now if you first want to apply the method y() on x and then on the result want to apply the z() method, you will write x.y().z(). This is like,
val = x.y()
result = val.z()
Example:
my_dict = {'key':'value'}
my_dict is a dict type object. my_dict.get('key') returns 'value' which is a str type object. now I can apply any method of str type object on it. which will be like,
my_dict.get('key').upper()
This will return 'VALUE'.
That is (sometimes a sign of) bad code.
It violates The law of Demeter. Here is a quote from Wikipedia explaining what is meant:
Each unit should have only limited knowledge about other units: only units "closely" related to the current unit.
Each unit should only talk to its friends; don't talk to strangers.
Only talk to your immediate friends.
Suppose you have a car, which itself has an engine:
class Car:
def __init__(self):
self._engine=None
#property
def engine(self):
return self._engine
#engine.setter
def engine(self, value):
self._engine = value
class Porsche_engine:
def start(self):
print("starting")
So if you make a new car and set the engine to Porsche you could do the following:
>>> from car import *
>>> c=Car()
>>> e=Porsche_engine()
>>> c.engine=e
>>> c.engine.start()
starting
If you are maing this call from an Object, it has not only knowledge of a Car object, but has too knowledge of Engine, which is bad design.
Additionally: if you do not know whether a Car has an engine, calling directly start
>>> c=Car()
>>> c.engine.start()
May result in an Error
AttributeError: 'NoneType' object has no attribute 'start'
Edit:
To avoid (further) misunterstandings and misreadings, from what I am saying.
There are two usages:
1) as I pointed out, Objects calling methods on other objects, returned from a third object is a violation of LoD. This is one way to read the question.
2) an exception to that is method chaining, which is not bad design.
And a better design would be, if the Car itself had a start()-Method which delegates to the engine.
I want to have something like
def x():
print get_def_name()
but not necessarily know the name of x.
Ideally it would return 'x' where x would be the name of the function.
You can do this by using Python's built-in inspect library.
You can read more of its documentation if you want to handle more complicated cases, but this snippet will work for you:
from inspect import getframeinfo, currentframe
def test_func_name():
return getframeinfo(currentframe()).function
print(test_func_name())
Functions in Python are objects, and as it happens those objects do have an attribute containing the name they were defined with:
>>> def x():
... pass
...
>>> print x.__name__
x
So, a naïve approach might be this:
>>> def x():
... print x.__name__
...
>>> x()
x
That seems to work. However, since you had to know the name of x inside the function in order to do that, you haven't really gained anything; you might have well just have done this:
def x():
print "x"
In fact, though, it's worse than that, because the __name__ attribute only refers to the name the function was defined with. If it gets bound to another name, it won't behave as you expect:
>>> y = x
>>> y()
x
Even worse, if the original name is no longer around, it won't work at all:
>>> del x
>>> y()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in x
NameError: global name 'x' is not defined
This second problem is one you can actually get around, although it's not pretty. The trick is to write a decorator that can pass the function's name into it as an argument:
>>> from functools import wraps
>>> def introspective(func):
... __name__ = func.__name__
... #wraps(func)
... def wrapper(*args, **kwargs):
... return func(__name__=__name__, *args, **kwargs)
... return wrapper
...
>>> #introspective
... def x(__name__):
... print __name__
...
>>> x()
x
>>> y = x
>>> y()
x
>>> del x
>>> y()
x
... although as you can see, you're still only getting back the name the function was defined with, not the one it happens to be bound to right now.
In practice, the short (and correct) answer is "don't do that". It's a fundamental fact of Python that objects don't know what name (or names) they're bound to - if you think your function needs that information, you're doing something wrong.
This sounds like you want to declare an anonymous function and it would return a reference to the new function object.
In Python, you can get a trivial anonymous function object with lambda but for a complex function it must have a name. But any function object is in fact an object and you can pass references around to it, so the name doesn't matter.
# lambda
sqr = lambda n: n**2
assert sqr(2) == 4
assert sqr(3) == 9
# named function
def f(n):
return n**2
sqr = f
assert sqr(2) == 4
assert sqr(3) == 9
Note that this function does have a name, f, but the name doesn't really matter here. We set the name sqr to the function object reference and use that name. We could put the function reference into a list or other data structure if we wanted to.
You could re-use the name of the function:
def f(n):
return n**2
sqr = f
def f(n):
return n**3
cube = f
So, while Python doesn't really support full anonymous functions, you can get the same effect. It's not really a problem that you have to give functions a name.
If you really don't want the function to have a name, you can unbind the name:
def f(n):
return n**2
lst = [f] # save function reference in a list
del(f) # unbind the name
Now the only way to access this function is through the list; the name of the function is gone.
I found a similar solution as Vazirani's, but I did a step forward to get the function object based on the name. Here is my solution:
import inspect
def named_func():
func_name = inspect.stack()[0].function
func_obj = inspect.stack()[1].frame.f_locals[func_name]
print(func_name, func_obj, func_obj.xxx)
named_func.xxx = 15
named_func()
Output is
named_func <function named_func at 0x7f3bc84622f0> 15
Unfortunately I cannot do this with lambda function. I keep trying.
What's the difference in python between
value = getValue()
and
value = getValue
?
Using parenthesis calls the function where as not using them creates a reference to that function.
See below:
>>> def t():
... return "Hi"
...
>>> a = t
>>> a
<function t at 0x01BECA70>
>>> a = t()
>>> a
'Hi'
>>>
Here is a good link to explain further: http://docs.python.org/2/tutorial/controlflow.html (scroll down to the "defining functions" part).
value = getValue() is a function call and assignment of the return value. It means "call function getValue with no arguments and make value refer to whatever it returns".
value = getValue says "make value refer to the same function that getValue refers to".
Just for the sake of curiosity I wanna know this..
I know scope of inner function is limited to outer function body only, but still is there any way so that we can access the inner function variable outside its scope or call the inner function outside its scope ?
In [7]: def main():
...: def sub():
...: a=5
...: print a
...:
In [8]: main()
In [9]: main.sub()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
/home/dubizzle/webapps/django/dubizzle/<ipython-input-9-3920726955bd> in <module>()
----> 1 main.sub()
AttributeError: 'function' object has no attribute 'sub'
In [10]:
>>> def main():
... def sub():
... a=5
... print a
...
>>> main.__code__.co_consts
(None, <code object sub at 0x2111ad0, file "<stdin>", line 2>)
>>> exec main.__code__.co_consts[1]
5
You can if you return the inner function as a value
>>> def main():
... def sub():
... a = 5
... print a
... return sub
...
>>> inner = main()
>>> inner()
5
or you can attach it to main as a property (functions are objects after all):
>>> def main():
... def sub():
... a = 5
... print a
... main.mysub = sub
...
>>> main()
>>> main.mysub()
5
but you better document your very good reason for doing this, since it will almost certainly surprise anyone reading your code :-)
No, you can't. The inner function is not an attribute of the outer function.
The inner function only exists after its def statement is executed (while the outer function is executed), and it stops to exist when the function exits.
You could return the inner function, of course.
A function is just another object in Python and can be introspected.
You can get the outer function body at runtime and parse/eval it to make the function available in the current namespace.
>>> import inspect
>>> def outer():
def inner():
print "hello!"
>>> inspect.getsourcelines(outer)
([u'def outer():\n', u' def inner():\n', u' print "hello!"\n'], 1)
Not really the same thing as calling outer.inner(), but if you are not making the inner function explicitly available outside the scope of the outer function, I guess it is the the only possibility.
For example, a very naive eval attempt could be:
>>> exec('\n'.join([ line[4:] for line in inspect.getsourcelines(outer)[0][1:] ]))
>>> inner()
hello!
An inner function is just a local variable like any other so the same rules apply. If you want to access it you have to return it.
Consider the following (broken) code:
import functools
class Foo(object):
def __init__(self):
def f(a,self,b):
print a+b
self.g = functools.partial(f,1)
x=Foo()
x.g(2)
What I want to do is take the function f and partially apply it, resulting in a function g(self,b). I would like to use this function as a method, however this does not currently work and instead I get the error
Traceback (most recent call last):
File "test.py", line 8, in <module>
x.g(2)
TypeError: f() takes exactly 3 arguments (2 given)
Doing x.g(x,2) however works, so it seem the issue is that g is considered a "normal" function instead of a method of the class. Is there a way to get x.g to behave like a method (i.e implicitly pass the self parameter) instead of a function?
There are two issues at hand here. First, for a function to be turned into a method it must be stored on the class, not the instance. A demonstration:
class Foo(object):
def a(*args):
print 'a', args
def b(*args):
print 'b', args
Foo.b = b
x = Foo()
def c(*args):
print 'c', args
x.c = c
So a is a function defined in the class definition, b is a function assigned to the class afterwards, and c is a function assigned to the instance. Take a look at what happens when we call them:
>>> x.a('a will have "self"')
a (<__main__.Foo object at 0x100425ed0>, 'a will have "self"')
>>> x.b('as will b')
b (<__main__.Foo object at 0x100425ed0>, 'as will b')
>>> x.c('c will only recieve this string')
c ('c will only recieve this string',)
As you can see there is little difference between a function defined along with the class, and one assigned to it later. I believe there is actually no difference as long as there is no metaclass involved, but that is for another time.
The second problem comes from how a function is actually turned into a method in the first place; the function type implements the descriptor protocol. (See the docs for details.) In a nutshell, the function type has a special __get__ method which is called when you perform an attribute lookup on the class itself. Instead of you getting the function object, the __get__ method of that function object is called, and that returns a bound method object (which is what supplies the self argument).
Why is this a problem? Because the functools.partial object is not a descriptor!
>>> import functools
>>> def f(*args):
... print 'f', args
...
>>> g = functools.partial(f, 1, 2, 3)
>>> g
<functools.partial object at 0x10042f2b8>
>>> g.__get__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'functools.partial' object has no attribute '__get__'
There are a number of options you have at this point. You can explicitly supply the self argument to the partial:
import functools
class Foo(object):
def __init__(self):
def f(self, a, b):
print a + b
self.g = functools.partial(f, self, 1)
x = Foo()
x.g(2)
...or you would imbed the self and value of a in a closure:
class Foo(object):
def __init__(self):
a = 1
def f(b):
print a + b
self.g = f
x = Foo()
x.g(2)
These solutions are of course assuming that there is an as yet unspecified reason for assigning a method to the class in the constructor like this, as you can very easily just define a method directly on the class to do what you are doing here.
Edit: Here is an idea for a solution assuming the functions may be created for the class, instead of the instance:
class Foo(object):
pass
def make_binding(name):
def f(self, *args):
print 'Do %s with %s given %r.' % (name, self, args)
return f
for name in 'foo', 'bar', 'baz':
setattr(Foo, name, make_binding(name))
f = Foo()
f.foo(1, 2, 3)
f.bar('some input')
f.baz()
Gives you:
Do foo with <__main__.Foo object at 0x10053e3d0> given (1, 2, 3).
Do bar with <__main__.Foo object at 0x10053e3d0> given ('some input',).
Do baz with <__main__.Foo object at 0x10053e3d0> given ().
This will work. But I'm not sure if this is what you are looking for
class Foo(object):
def __init__(self):
def f(a,self,b):
print a+b
self.g = functools.partial(f,1, self) # <= passing `self` also.
x = Foo()
x.g(2)
this is simply a concrete example of what i believe is the most correct (and therefore pythonic :) way to solve -- as the best solution (definition on a class!) was never revealed -- #MikeBoers explanations are otherwise solid.
i've used this pattern quite a bit (recently for an proxied API), and it's survived untold production hours without the slightest irregularity.
from functools import update_wrapper
from functools import partial
from types import MethodType
class Basic(object):
def add(self, **kwds):
print sum(kwds.values())
Basic.add_to_one = MethodType(
update_wrapper(partial(Basic.add, a=1), Basic.add),
None,
Basic,
)
x = Basic()
x.add(a=1, b=9)
x.add_to_one(b=9)
...yields:
10
10
...the key take-home-point here is MethodType(func, inst, cls), which creates an unbound method from another callable (you can even use this to chain/bind instance methods to unrelated classes... when instantiated+called the original instance method will receive BOTH self objects!)
note the exclusive use of keyword arguments! while there might be a better way to handle, args are generally a PITA because the placement of self becomes less predictable. also, IME anyway, using *args, and **kwds in the bottom-most function has proven very useful later on.
functools.partialmethod() is available since python 3.4 for this purpose.
import functools
class Foo(object):
def __init__(self):
def f(a,self,b):
print a+b
self.g = functools.partialmethod(f,1)
x=Foo()
x.g(2)