how can i use '#' by myself function like '#staticmethod' - python

the next is my code,it can print 'xxx', but run wrong at last:
def a(object):
print 'xxx'
#a
def b():
return 'bbb'
b()
In your answers, please try to use code examples rather than text, because my English is not very good. Thank you.

The decorator form #a means:
#a
def b...
is exactly the same as:
def b...
b = a(b)
So, write a as a higher order function, AKA HOF: specifically, a function that takes a function object as an argument, and returns a function object.
As you give NO idea in your question about what a is supposed to DO, you're really making it impossible to give a code example that makes any sense whatsoever: good English or not, you're really polluting SO, not contributing to it, by your questions, since you never explain WHAT are you trying to accomplish in your code!!!

def a(b):
print 'xxx'
return b
#a
def b():
return 'bbb'
b()
This is the same as:
def a(b):
print 'xxx'
return b
def b():
return 'bbb'
b = a(b)
b()

Related

Python decorator #property behaviour in class [duplicate]

Here's a snippet of code.
class TestClass:
def __init__(self):
self.a = "a"
print("calling init")
#property
def b(self):
b = "b"
print("in property")
return b
test_obj = TestClass()
print("a = {} b = {}".format(test_obj.a,test_obj.b))
I'm trying to understand when the variable b defined inside test_obj gets its value of "b".
As you can see from the below screenshot, the statement on line 13 is yet to be evaluated/executed but already the value of b for test_obj has been initialized. Debugging this by placing a breakpoint on literally every single line didn't help me understand how this is happening.
Can someone please explain this to me ?
More likely, the IDE is trying to show you what the value of test_obj.b is. For that it gets the value from test_obj.b. Since it doesn't make much of a difference whether b is an attribute or a #property, the debugger essentially just does test_obj.b for you, which gives it the value 'b'.
The function def b works exactly as you might expect from any other ordinary function; it's just that the debugger/IDE implicitly invokes it for you.

Call nested function from another function in python?

I have a function inside inside another and a third function. How can I call my nested function inside of my third function? Is there any special libraries I can use? I am not allowed to edit a() or b(), only c().
def a():
def b():
print("hi")
def c():
# code only here to call b() to print
When you do this, function b is defined locally within a. This means that it cannot be accessed by default outside of a. There are two main ways to solve this, but both involve modifying a:
The global keyword (not recommended)
def a():
global b
def b():
print("hi")
Here the global keyword sets b up as a global variable, so that you can then access it by calling it normally from within c. This is generally frowned upon.
Returning the function from a and passing it to c
def a():
def b():
print("hi")
return b
def c(b):
#your code
Then, when you call c, you should pass b to it, which a will have returned. You can either do so thus:
b = a()
c(b)
Or you can simply call a every time you call c, thus:
c(a())
If you choose to do this, you can then define c thus:
def c():
b = a()
#your code here
which would allow you to simply call c normally, thus:
`c()`
This is not possible due to the way that Python scope works. b() is local to a(), and so does not exist within c().
EDIT: commenter is correct, the suggestion I initially gave doesn't work -- so this definitely just isn't possible.
As explained here, you cannot directly call a function included inside another. But, you can play around a bit and make it indirectly possible.
You could try calling functions via arguments and parameter values to call the function you want inside another function.
def a(invoke=None):
def b():
print('b')
if invoke == 'b':
b()
def c():
a(invoke='b')
c()
The result is:
b
You can even pass arguments to these function if you want:
def a(invoke=None, a_parameter=None):
def b(b_parameter=None):
if b_parameter == None:
print('b')
if b_parameter == 'b1':
print('b1')
if b_parameter == 'b2':
print('b2')
if invoke == 'b':
b(b_parameter = a_parameter)
def c(parameter=None):
a(invoke='b', a_parameter = parameter)
c()
Result:
b
But:
c('b1')
Result:
b1

List of objects function not working

Sorry for the title, I hope it reflects correctly my problem :
In the following code, I was expecting the result to be result 0 1 2 but instead I have 2 2 2. The code inside my_function seems to be interpreted with the last instance of obj. What is wrong ?
class Example:
def __init__(self, x):
self.x = x
def get(self):
return self.x
a_list = []
for index in range(3):
obj = Example(index)
def my_function(x):
#some stuff with x like obj.another_function(x)
return obj.get()
a_list.append(my_function)
for c in a_list:
print(c())
When you define this
def my_function():
return obj.get()
Python will understand that my_function should run the get() method of an object called obj and return the value. It won't know the value of obj and what the get() method does until you attempt to call it.
So, you are actually defining three different functions that will eventually do the same thing. And, in the end, running the same code thrice.
But why is the return 2 2 2?
Because after the last iteration, the value of obj is Example(2)* because you redefine its value at every iteration, and the last one remains.
*
because of this line obj = Example(index)
Understanding a few things about how python works will help you understand what's happening here. Here obj is a closure, closures are evaluated at call time, not when the function is defined so if I do this:
x = "hello"
def printX():
print x
x = "goodbye"
printX() # goodbye
I get "goodbye" because printX is referencing a global variable in my module, which changes after I create printX.
What you want to do is create a function with a closure that references a specific object. The functional way to do this is to create a function that returns another function:
x = "hello"
def makePrintX(a):
def printX():
# We print a, the object passed to `makePrintX`
print a
return printX
# x is evaluated here when it is still "hello"
myPrintX = makePrintX(x)
x = "goodbye"
myPrintX() # "hello"
If you're having trouble understanding the above example I would recommend reading up on python's scoping rules. For your example, you could do something like this:
class Example:
def __init__(self, x):
self.x = x
def get(self):
return self.x
def makeObjFunction(obj):
def objFunction(x):
return obj.get()
return objFunction
a_list = []
for index in range(3):
obj = Example(index)
my_function = makeObjFunction(obj)
a_list.append(my_function)
for c in a_list:
print(c("some value"))
You are appending three my_functions to the a_list which are all closures over the same Example object. Try:
def my_function():
return obj
<__main__.Example object at 0x0054EDF0>
<__main__.Example object at 0x0054EDF0>
<__main__.Example object at 0x0054EDF0>
You can see they have the same id so calling get() on each should give the same answer.
If you just append the obj.get function (and drop the my_function) it'll work fine.
a_list.append(obj.get)
....
0
1
2
Edit: You've updated your question so to let you do more stuff in my_function(). It's still basically a scoping problem.
def my_func_factory(p_obj):
def my_function(x):
#some stuff with x like obj.another_function(x)
return p_obj.get()
return my_function
for index in range(3):
obj = Example(index)
a_list.append(my_func_factory(obj))
Since my_function can't see obj being reassigned, each instance doesn't pick up the change.
I think append() during the for just append the function address in a_list[]. After for iteration, the a_list is really given the number. Then it discovers the address of my_function, and they get the number in my_function, this is, 2. That's why you get [2,2,2].
Or maybe, in my_function, function give the method of "obj". But for iteration change the "obj" memory address each time, so the symbol "obj" always aim to the newest object Example. Due to my_function always get "obj", you get the same number from the last object.

What is the Pythonic way to avoid reference before assignment errors in enclosing scopes?

I'm speaking about the general case. Here's an example:
c = 1
def a():
def b():
print(c)
b()
c = 2
a()
This code will return the following error:
NameError: free variable 'c' referenced before assignment in enclosing scope. While the logical assumption is that the output should be 1. What is the Pythonic solution to this issue? Use the global or nonlocal statements (which I don't like)? Maybe just avoid such situations, where multiple scopes share variables with identical names?
Passing it as a parameter
When passing a outside variable as a parameter, avoid reusing names unless it's not possible that this variable can handle any other variable as parameter, then it doesn't really matter otherwise it will be confusing if you pass d the next time and you do operations on c within the function.
Secondly, the value of c will not get modified within the function even if changing name from param to c (it has very little meaning) when passing as a variable because it's not considered as a global varaible, even tho the variable is an object it will only be a object in this function unless you pass it into a class.
c = 1
def a(param):
def b():
print(param)
b()
param = 2
a(c)
You would need to stick to the global option if you don't want to pass it as a parameter and you still want to affect c outside of your function.
The global option will affect the "outside" c variable as your want it to.. but this is not really considered best practice, avid it if possible.
c = 1
def a():
global c
def b():
print(c)
b()
c = 2
a()
Here's what i would recommend:
c = 1
def a(param):
def b():
print(param)
b()
param = 2
return param
c = a(c)
Or even:
c = 1
def b(param):
print(param)
def a(param):
b(param)
param = 2
return param
c = a(c)

Will the function in python for loop be executed multiple times?

Say I have the following class with a method returning a list:
class C:
def f(self):
return [1,2,3]
If I loop over the list returned fro the method, as follows:
c = C()
for i in c.f():
print(i)
Inside the for loop, will c.f() be executed multiple times? If yes, in order to get it once, do I have to do assignment outside of the loop, or there is some trivial way?
In [395]: def tester():
...: print "Tester Called!"
...: return [1,2,3]
In [396]: for i in tester():
...: pass
Tester Called!
Seems the answer is no.
from the python docs:
The for statement is used to iterate over the elements of a sequence
(such as a string, tuple or list) or other iterable object:
for_stmt ::= "for" target_list "in" expression_list ":" suite
["else" ":" suite]
The expression list is evaluated once; it should yield an iterable object.
c.f() will not get executed multiple times.
You didn't ask, but you might be curious about generators.
Your example as a generator would be as follows:
class C:
def f():
yield 1
yield 2
yield 3
The loop where you iterate over the results would be unchanged.
It will be executed only once. But there will be syntax errors in your code:
class , not Class
def f(self), not def f()
Did you try to test it yourself? The answer to your question is NO.
Here is how you should have tested it. Moreover there were lot of flaws in your code. Check the self commented modified version below
>>> class C: #its class not Class and C not C()
def f(self): #You were missing the self argument
print "in f" #Simple Test to validate your query
return [1,2,3]
>>> c=C()
>>> for i in c.f():
print i
in f
1
2
3
>>>
Though this example is trivial but still I will use this as an example to explain how we can leverage the power of functional programming of Python. What I will try to explain is called lazy evaluation or generator functions(http://docs.python.org/glossary.html#term-generator).
Consider the modified example
>>> class C: #its class not Class and C not C()
def f(self): #You were missing the self argument
print "in f" #Simple Test to validate your query
for i in [1,2,3]:
yield i #Generates the next value when ever it is requsted
return #Exits the Generator
>>> c=C()
>>> for i in c.f():
print i
in f
1
2
3
>>>
Can you spot the difference?
No it is executed once.
And your method is not correctly defined. Should have a self argument:
class C:
def f(self):
return [1,2,3]

Categories

Resources