is this the proper use of 'in' in a conditional statement? - python

This is an overly simplified version of the problem that I'm working on. It's crude and basic but I just started out with python and wanna make sure that I have my basics straightened out.
I can't seem to get the desired output with this. For ex: When the list generated by a() contains '2', when I call out b() it does not give me the required value of y, which in this case should be 2.
from random import choice, sample
def a():
a = sample(range(0,5),2)
a.append(1)
return a
def b():
if 3 in a():
y = 1
elif 2 in a():
y = 2
else:
pass
return y
print a()
print b()

There are a few problems with your program, most notably, you are calling a within b, which I don't think you want to do. Within b, you are regenerating a list of new random values and then checking the contents of this list.
Also, you should not use pass in your else statement because you could imagine the possibility where y is never defined, and therefore you will fail to return something. I would suggest the following:
from random import choice, sample
def a():
a = sample(range(0,5),2)
a.append(1)
return a
def b(a):
if 3 in a:
return 1
elif 2 in a:
return 2
else:
return
a_output = a()
print a_output
print b(a_output)
However, this is an odd way to check the contents of a list. Without knowing the purpose of your program, it is difficult to make a recommendation for an alternative way to write a more pythonic function.

Related

How to use Loop inside Function corectly

i want use loop correctly inside function
This is my code :
def test():
for i in range(1,10):
return i
def check():
print(test())
check()
output is 1
i want to full iteration
output : 1 ,2,4....10
When you return inside a function, it immediately terminates the function and returns the specified value. This means that it goes into the for loop and returns 1, then stops running. One way to get around this is to use the yield keyword instead of return.
def test():
for i in range(1, 10):
yield i
This will make test() a generator, which can then be printed in check by unpacking its values.
def check():
print(*test())
Alternative ways of doing this would be to return a list in test() or to simply print the values within test() itself.
In Python (as with almost all programming languages), functions can only return once (ish). As soon as Python encounters return, it'll exit the function.
Python does have a feature called "generators", though: with the yield keyword, you can (sort of) return more than once:
def test():
for i in range(1,10):
yield i
To expand those values to the print function's arguments, use * like so:
def check():
print(*test())
>>> check()
1 2 3 4 5 6 7 8 9
>>> sum(test())
45
wim points out that you can sometimes return more than once from a function – but later return statements will "replace" the return value from earlier ones.
>>> def f():
... try:
... return 1
... finally:
... return 2
...
>>> f()
2
Unfortunately, CPython's optimising this too much for me to make sense of the dis bytecode decompilation; I have no idea how this works under the hood.
If you want to return all the values in the range you can do something like this:
def test():
return [i for i in range(1,10)]
def check():
print(test())
check()

Python: is there a way to list all the functions defined inside a function? [duplicate]

In python you can do fname.__code__.co_names to retrieve a list of functions and global things that a function references. If I do fname.__code__.co_varnames, this includes inner functions, I believe.
Is there a way to essentially do inner.__code__.co_names ? by starting with a string that looks like 'inner', as is returned by co_varnames?
In Python 3.4+ you can get the names using dis.get_instructions. To support nested functions as well you need to recursively loop over each code object you encounter:
import dis
import types
def get_names(f):
ins = dis.get_instructions(f)
for x in ins:
try:
if x.opcode == 100 and '<locals>' in next(ins).argval\
and next(ins).opcode == 132:
yield next(ins).argrepr
yield from get_names(x.argval)
except Exception:
pass
Demo:
def func():
x = 1
y = 2
print ('foo')
class A:
def method(self):
pass
def f1():
z = 3
print ('bar')
def f2():
a = 4
def f3():
b = [1, 2, 3]
def f4():
pass
print(list(get_names(func)))
Outputs:
['f1', 'f2', 'f3', 'f4']
I don't think you can inspect the code object because inner functions are lazy, and their code-objects are only created just in time. What you probably want to look at instead is the ast module. Here's a quick example:
import ast, inspect
# this is the test scenario
def function1():
f1_var1 = 42
def function2():
f2_var1 = 42
f2_var2 = 42
def function3():
f3_var1 = 42
# derive source code for top-level function
src = inspect.getsource(function1)
# derive abstract syntax tree rooted at top-level function
node = ast.parse(src)
# next, ast's walk method takes all the difficulty out of tree-traversal for us
for x in ast.walk(node):
# functions have names whereas variables have ids,
# nested-classes may all use different terminology
# you'll have to look at the various node-types to
# get this part exactly right
name_or_id = getattr(x,'name', getattr(x,'id',None))
if name_or_id:
print name_or_id
The results are: function1, function2, f1_var1, function3, f2_var1, f2_var2, f3_var1. Obligatory disclaimer: there's probably not a good reason for doing this type of thing.. but have fun :)
Oh and if you only want the names of the inner functions?
print dict([[x.name,x] for x in ast.walk(ast.parse(inspect.getsource(some_function))) if type(x).__name__=='FunctionDef'])

loop, python, define a series of variables and functions

I am new to Python and have difficulties to understand how to use loop.
could anyone help me how to write below code in a loop/list, which will be much shorter?
def a1(self):
if aorb1 == 1:
return texta1
return textb1
def a2(self):
if aorb2 == 1:
return texta2
return textb2
def a3(self):
if aorb3 == 1:
return texta3
return textb3
Thanks a lot.
I can take a stab at what direction you are going and provide some level of guidance, but I suspect that I won't go the correct direction without more information.
First off, you don't need self as a parameter. That only applies to objects.
Next, you do need to provide the variables used within the function as parameters. It looks like you tried to use a and b without declaring them.
def a1(a, b)
if a == 1:
return texta
elif b == 1:
return textb
Be careful that you don't miss any cases. What if a = 0 and b = 0? Then this function would return None.
Finally, I'm not sure exactly what you are trying to do with the loop, but perhaps something like this?
# assign a and b values somewhere
a = 1
b = 0
# save the functions in a list
my_functions = [a1, a2, a3]
# execute each function with the parameters `a` and `b`
for f in my_functions:
result = f(a, b)
x.append(result)
This will result in a list containing the results of your function executions with parameters a and b. Would like to help more, but we need more information. Perhaps the above will stimulate that.
You could generate lambdas where you pass a and b, as follows:
my_funcs = []
for i in range(1,4):
func = lambda a, b: textas[i] if a == 1 or b == 1 else textbs[i]
my_funcs.append(func)
You can call such a function like this:
my_funcs[0](0,1) # this does the same as your function a1
I don't know what you want texta1 or textb1 to be. This could be stored in a dictionary, like I do in the example above.

Python: __cmp__ and testing list membership

Apologies if someone has already addressed this, but I couldn't find an answer.
I have a problem where I overrode __cmp__ for a custom class, similar to this:
class MyClass(object):
def __init__(self, prop):
self.prop = prop
def __cmp__(self, other):
return cmp(self.prop, other.prop)
a = MyClass(1)
b = MyClass(2)
c = MyClass(3)
d = MyClass(1)
my_list = [a, b, c]
print a in my_list
print b in my_list
print c in my_list
print d in my_list
# Output:
#
# True
# True
# True
# True
Reading the docs tells me that this is expected, because:
For the list and tuple types, x in y is true if and only if there exists an index i such that x == y[i] is true.
My question is two-fold:
Why does Python (2.7) use == rather than is to test list membership?
Is there a better way to be doing this, such that I can test whether a specific instance of my class is actually in a container and be able to compare instances based on their attributes?
Why does Python (2.7) use == rather than is to test list membership?
Because equality is usually more interesting than identity for containment checking, especially when two different objects can have the same value.
>>> ('Hello, ' + 'world!') is 'Hello, world!'
False
>>> ('Hello, ' + 'world!') == 'Hello, world!'
True
Is there a better way to be doing this, such that I can test whether a specific instance of my class is actually in a container and be able to compare instances based on their attributes?
Not especially.
The list contains a value equal to the variable, not a reference to the variable. Think about it this way. Are these two code samples the same? What makes them different?
class Person:
def __init__(self, name):
self.name = name
def __eq__(self, other):
return self.name == other.name
# sample one
sam = Person('Sam')
bob = Person('Bob')
people = [sam, bob]
The first sample is when you should use the is keyword. You're trying to test if the object in the list is the object outside of the list, meaning the sam inside the list is stored in the same place in memory as the sam outside the list.
# sample two
sam = Person('Sam')
bob = Person('Bob')
people = [Person('Sam'), Person('Bob')]
This sample is when you should use the double equals keyword. You're trying to test if the object in the list has the value when compared to the object outside of the list. Notice, that because we instantiated to different people with the name Sam, they will be equal in value but not the same object.

Can you assign to a variable defined in a parent function? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Python nested functions variable scoping
After much trial and error I have eventually discovered that this doesn't work:
def a():
def b():
print x
x=2
x = 1
b()
print x
You get an exception (x not defined before being referenced). So it looks like b can read from x, but if it tries to assign to it, Python changes its interpretation of 'x' to be a local variable, which is now not defined.
Question for my own sick curiosity: is there any way of achieving this? Is there a way of explicitly accessing the scope of the parent function? (x is not global)
The nonlocal statement in Python 3 will do this.
Edit: In Python 2, there's not a simple way to do it. I suggest you use some mutable container object if you need this capability. For example:
def a():
def b():
print d["x"]
d["x"]=2
d = dict(x=1)
b()
print d["x"]
If you absolutely must emulate nonlocal for CPython 2, you can hack it with the Python C API this way:
import ctypes
import inspect
locals_to_fast = ctypes.pythonapi.PyFrame_LocalsToFast
locals_to_fast.restype = None
locals_to_fast.argtypes = [ctypes.py_object, ctypes.c_int]
def set_in_frame(frame, name, value):
frame.f_locals[name] = value
locals_to_fast(frame, 1)
def a():
def b(frame=inspect.currentframe()):
print x
set_in_frame(frame, "x", 2)
x = 1
b()
print x
You could also set the frame local, and instead of calling PyFrame_LocalsToFast(), you could manipulate the bytecode of a so that it uses LOAD_NAME instead of LOAD_FAST. Please don't do either of these things. There is surely a better solution for your use case.

Categories