Python: function and variable with the same name - python

Why can't I call the function again? Or, how can I make it?
Suppose I have this function:
def a(x, y, z):
if x:
return y
else:
return z
and I call it with:
print a(3>2, 4, 5)
I get 4.
But imagine that I declare a variable with the same name that the function (by mistake):
a=2
Now, if I try to do:
a=a(3>4, 4, 5)
or:
a(3>4, 4, 5)
I will get this error: "TypeError: 'int' object is not callable"
Is it not possible to assign the variable 'a' to the function?

After you do this:
a = 2
a is no longer a function, it's just an integer (you reassigned it!). So naturally the interpreter will complain if you try to invoke it as if it were a function, because you're doing this:
2()
=> TypeError: 'int' object is not callable
Bottom line: you can't have two things simultaneously with the same name, be it a function, an integer, or any other object in Python. Just use a different name.

names in Python are typically identifiers for a specific type, more like naming a box which stores a variable/function/method or any object in Python. When you are reassigning, you are just renaming a box.
You can find that out by doing the below.
Initially, a is assigned a value 9, at location 140515915925784.
As soon as I use the same identifier for a function , a now refers to a box containing the address of that function in 4512942512
Reassigning a to 3 again points a to refer to a different address.
>>> a = 9
>>> id(a)
140515915925784
>>> def a(x):
... return x
...
>>> id(a)
4512942512
>>> a
<function a at 0x10cfe09b0>
>>>
>>>
>>>
>>> a = 3
>>> id(a)
140515915925928
>>> a
3
>>>

You're assigning the name a to a function definition, and then reassigning it to an integer.
It's syntactically correct, but it's not what you want.
It's best to give functions semantic names that describe what you're doing with the arguments being passed to them, and to give variables semantic names that describe what object they're pointing to. If you do that, you'll have more readable code and you certainly won't make this mistake again.

Related

Is it bad form to override the "dot" operator in Python?

Usually, a period in Python denotes class membership:
class A:
a = 1
>>> A.a
1
Sometimes the language doesn't seem quite flexible enough to completely express an idea from domains outside of computer science though. Consider the following example which (fairly brittly for brevity) uses the same operator to seem like something completely different.
class Vector:
def __init__(self, data):
self.data = list(data)
def dot(self, x):
return sum([a*b for a, b in zip(self.data, x.data)])
def __getattr__(self, x):
if x == 'Vector':
return lambda p: self.dot(Vector(p))
return self.dot(globals()[x])
Here we've taken over __getattr__() so that in many scenarios where Python would attempt to find an attribute from our vector it instead computes the mathematical dot product.
>>> v = Vector([1, 2])
>>> v.Vector([3, 4])
11
>>> v.v
5
If such behavior is kept restricted in scope to the domain of interest, is there anything wrong with such a design pattern?
It's a bad idea.
Why? Because the "dot operator", as you call it, isn't really an operator to begin with. That's because the "operand" on the right-hand side is interpreted as a string, not as an expression. This may seem insignificant to you, but it has plenty of problematic consequences:
Python programmers are used to foo.bar meaning "Take the bar attribute of the foo object". Turning the dot into a dot product operator breaks this expectation and will confuse people who read your code. It's unintuitive.
It's ambiguous, because you cannot know if the user is trying to calculate a dot product or access an attribute. Consider:
>>> data = Vector([1, 2])
>>> v.data # dot product or accessing the data attribute?
Keep in mind that methods are attributes, too:
>>> dot = Vector([1, 2])
>>> v.dot # dot product or accessing the dot method?
Because the right-hand operand is interpreted as a string, you have to jump through a whole bunch of hoops to turn that string into something useful - as you've tried to do with globals()[x], which looks up a variable in the global scope. The problem is that - in certain situations - it's completely impossible to access a variable just by its name. No matter what you do, you will never be able to access a variable that no longer exists because it's already been garbage collected:
def func():
v2 = Vector([1, 2])
def closure_func():
return v.v2 # this will never work because v2 is already dead!
return closure_func
closure_func = func()
result = closure_func()
Because the right-hand operand is a string, you cannot use arbitrary expressions on the right-hand side. You're limited to variables; trying to use anything else on the right-hand side will throw some kind of exception. And to make it worse, it won't even throw the appropriate TypeError like other operators would:
>>> [] + 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "int") to list
>>> v.1
File "<stdin>", line 1
v.1
^
SyntaxError: invalid syntax
Unlike real operators, the "dot operator" can only be implemented in the left-hand operand. All other operators can be implemented in either one of two corresponding dundermethods, for example __add__ and __radd__ for the + operator. Example:
>>> class Incrementer:
... def __radd__(self, other):
... return other + 1
...
>>> 2 + Incrementer()
3
This isn't possible with your dot product:
>>> my_v = MyCustomVector()
>>> v.my_v
AttributeError: 'MyCustomVector' object has no attribute 'data'
Bottom line: Implementing a dot method in your Vector class is the way to go. Since the dot isn't a real operator, trying to turn it into one is bound to backfire.
I would not recommend it. What do you mean by "the language isn't flexible enough to express an idea"? In your example, v.dot(u) is expressive and has the desired effect. This is, by the way, exactly how numpy does it.
If you want to use vectors, there's a special method name that isn't mentioned in th most part called __matmul__. This comes with its corresponding in-place and reflected methods __imatmul__ and __rmatmul__. The operator is an #:
a # b
# corresponds to
a.__matmul__(b)

Difference between 'lambda' and 'def' statement? [duplicate]

I'm curious about the difference between lambda function and a regular function (defined with def) - in the python level. (I know what is the difference for programmers and when to use each one.)
>>> def a():
return 1
>>> b = lambda: 1
>>> a
<function a at 0x0000000004036F98>
>>> b
<function <lambda> at 0x0000000004031588>
As we can see - python knows that b is a lambda function and a is a regular function. why is that? what is the difference between them to python?
They are the same type so they are treated the same way:
>>> type(a)
<type 'function'>
>>> type(b)
<type 'function'>
Python also knows that b was defined as a lambda function and it sets that as function name:
>>> a.func_name
'a'
>>> b.func_name
'<lambda>'
In other words, it influences the name that the function will get but as far as Python is concerned, both are functions which means they can be mostly used in the same way. See mgilson's comment below for an important difference between functions and lambda functions regarding pickling.
The only difference is that (a) the body of a lambda can consist of only a single expression, the result of which is returned from the function created and (b) a lambda expression is an expression which evaluates to a function object, while a def statement has no value, and creates a function object and binds it to a name.
In all other material respects they result in identical objects - the same scope and capture rules apply. (Immaterial differences are that lambda-created functions have a default func_name of "<lambda>". This may affect operation in esoteric cases - e.g. attempts to pickle functions.).
Both lambda and def create the same kind of function – they have the same kind of metadata and capabilities. Their technical difference is syntactical:
A lambda is an expression producing a function.
A def is a statement producing a function.
This is everything that dictates how they can be used. Other apparent differences simply come from the information lambda/def can capture.
>>> def def_func(): pass
>>> lambda_func = lambda: None
>>> type(def_func) == type(lambda_func)
True
Usage: Expression vs. Statement
A lambda is more flexible as expressions can be part of more language constructs.
# v--------------v arguments must be expressions
sort(values, key=lambda x: abs(x))
In contrast, a def is more powerful as it can consist of more language constructs.
def encode(num, base):
while num: # statements must be inside statements
num, bit = divmod(num, base)
yield bit
These differences derive directly from one being an expression and the other being a statement. Python has no special rules to decide where a lambda/def may be used.
Where the wild <lambda>s grow
The primary reason to assume lambda and def correspond to different kinds of function is metadata: lambda is often referred to as an "anonymous function" and miraculously it always produces a function <lambda>. Other quirks include "lambda functions can't be pickled", and recently typing also does "not work" for lambda.
That is because compared to def syntax, the lambda syntax has no way of specifying name, type annotations and similar. As such, Python simply fills in sane defaults for either: the name becomes <lambda> and annotations are left empty.
>>> identity = lambda a: a
>>> identity.__qualname__
'<lambda>'
>>> identity.__annotations__
{}
Since <lambda> is not a valid identifier, everything using this metadata to find the function – most prominently pickle – fails.
However, that does not make the function an "anonymous function" type. The metadata can be patched up to insert what def would provide:
>>> identity.__qualname__ = identity.__name__ = 'identity'
>>> identity
<function __main__.identity(a)>
Of course at that one point one can just use def…
First consider the diff b/w the two.
Lambda functions: are operator can have any number of arguments, but it can have only one expression. It cannot contain any statements and it returns a function object which can be assigned to any variable. They can be used in the block they were created.
def functions: Functions help break our program into smaller and modular chunks. As our program grows larger and larger, functions make it more organised and manageable. They can be called and used anywhere we want.
Here you can get more clear difference by following example.
Defining a function
def add(a,b):
return a+b
print(add(4,5))
Defining a lambda
add = lambda x, y : x + y
print(add(4,5))
Lambda is an inline function where we can do any functionality without a function name.
It is helpful when we use it as an argument to a higher-order function.
Eg: A function that takes in other functions as arguments.
Example of Function definition:
>>> def func(a, b):
return a * b
>>> func(2,3)
6
>>> type(func)
<class 'function'>
>>> func
<function func at 0x034B6E88>
Example of Lambda expression:
>>> multiply = lambda a, b: a * b
>>> multiply(2, 3)
6
>>> type(multiply)
<class 'function'>
>>> multiply
<function <lambda> at 0x034B6ED0>
Both returns same output value. Only object returned are different. "func" name for Function and for Lambda.
lambda creates an anonymous function. This idea has been taken from functional programming languages. In this way you can create and pass the function to other functions like map and filter. (look here)
You can pass normal functions to these functions too, but since mostly they are simple and they are not used anywhere else, it's inconvenient to go through the whole process of definfing a new function.
As an example take a look at this:
>>> a = [1, 2, 3, 4]
>>> print map( lambda x : x*2 + 1, a )
[3, 5, 7, 9, 11]

Python: item.method() and function(item)

What is the logic for picking some methods to be prefixed with the items they are used with, but some are functions that need items as the arguments?
For example:
L=[1,4,3]
print len(L) #function(item)
L.sort() #item.method()
I thought maybe the functions that modify the item need to be prefixed while the ones that return information about the item use it as an argument, but I'm not too sure.
Edit:
What I'm trying to ask is why does python not have L.len()? What is the difference between the nature of the two kinds of functions? Or was it randomly chosen that some operations will be methods while some will be functions?
One of the principles behind Python is There is Only One Way to Do It. In particular, to get the length of a sequence (array / tuple / xrange...), you always use len, regardless of the sequence type.
However, sorting is not supporting on all of those sequence types. This makes it more suitable to being a method.
a = [0,1,2]
b = (0,1,2)
c = xrange(3)
d = "abc"
print len(a), len(b), len(c), len(d) # Ok
a.sort() # Ok
b.sort() # AttributeError: 'tuple' object has no attribute 'sort'
c.sort() # AttributeError: 'xrange' object has no attribute 'sort'
d.sort() # AttributeError: 'str' object has no attribute 'sort'
Something that may help you understand a bit better: http://www.tutorialspoint.com/python/python_classes_objects.htm
What you describe as item.function() is actually a method, which is defined by the class that said item belongs to. You need to form a comprehensive understanding of function, class, object, method and maybe more in Python.
Just conceptually speaking, when you call L.sort(), the sort() method of type/class list actually accepts an argument usually by convention called self that represents the object/instance of the type/class list, in this case L. And sort just like a standalone sorted function but just applies the sorting logic to L itself. Comparatively, sorted function would require an iterable (a list, for example), to be its required argument in order to function.
Code example:
my_list = [2, 1, 3]
# .sort() is a list method that applies the sorting logic to a
# specific instance of list, in this case, my_list
my_list.sort()
# sorted is a built-in function that's more generic which can be
# used on any iterable of Python, including list type
sorted(my_list)
There's a bigger difference between methods and functions than just their syntax.
def foo():
print "function!"
class ExampleClass(object):
def foo(self):
print "method!"
In this example, i defined a function foo and a class ExampleClass with 1 method, foo.
Let's try to use them:
>>> foo()
function!
>>> e = ExampleClass()
>>> e.foo()
method!
>>> l = [3,4,5]
>>> l.foo()
Traceback (most recent call last):
File "<pyshell#7>", line 1, in <module>
l.foo()
AttributeError: 'list' object has no attribute 'foo'
>>>
Even though both have the same name, Python knows that if you do foo(), your calling a function, so it'll check if there's any function defined with that name.
And if you do a.foo(), it knows you're calling a method, so it'll check if there's a method foo defined for objects of the type a has, and if there is, it will call it. In the last example, we try that with a list and it gives us an error because lists don't have a foo method defined.

Assign results of function call in one line in python

How can I assign the results of a function call to multiple variables when the results are stored by name (not index-able), in python.
For example (tested in Python 3),
import random
# foo, as defined somewhere else where we can't or don't want to change it
def foo():
t = random.randint(1,100)
# put in a dummy class instead of just "return t,t+1"
# because otherwise we could subscript or just A,B = foo()
class Cat(object):
x = t
y = t + 1
return Cat()
# METHOD 1
# clearly wrong; A should be 1 more than B; they point to fields of different objects
A,B = foo().x, foo().y
print(A,B)
# METHOD 2
# correct, but requires two lines and an implicit variable
t = foo()
A,B = t.x, t.y
del t # don't really want t lying around
print(A,B)
# METHOD 3
# correct and one line, but an obfuscated mess
A,B = [ (t.x,t.y) for t in (foo(),) ][0]
print(A,B)
print(t) # this will raise an exception, but unless you know your python cold it might not be obvious before running
# METHOD 4
# Conforms to the suggestions in the links below without modifying the initial function foo or class Cat.
# But while all subsequent calls are pretty, but we have to use an otherwise meaningless shell function
def get_foo():
t = foo()
return t.x, t.y
A,B = get_foo()
What we don't want to do
If the results were indexable ( Cat extended tuple/list, we had used a namedtuple, etc.), we could simply write A,B = foo() as indicated in the comment above the Cat class. That's what's recommended here , for example.
Let's assume we have a good reason not to allow that. Maybe we like the clarity of assigning from the variable names (if they're more meaningful than x and y) or maybe the object is not primarily a container. Maybe the fields are properties, so access actually involves a method call. We don't have to assume any of those to answer this question though; the Cat class can be taken at face value.
This question already deals with how to design functions/classes the best way possible; if the function's expected return value are already well defined and does not involve tuple-like access, what is the best way to accept multiple values when returning?
I would strongly recommend either using multiple statements, or just keeping the result object without unpacking its attributes. That said, you can use operator.attrgetter for this:
from operator import attrgetter
a, b, c = attrgetter('a', 'b', 'c')(foo())

Python automatic class assignment

In python. when I write x = 5, x becomes an instance of int automatically. But suppose I have defined a new class say number and I want x to become an instance of number instead of int when I assign it the value 5. Is this possible?
ie, Instead of this -->
>>> x = 5
>>> type(x)
<type 'int'>
Is this possible:
>>> x = 5
>>> type(x)
<type 'number'>
No. You would have to write a monkey patch to achieve this, that is incredibly unpythonic, can you simply not write
x = number(5)
:)
Note that you really should never do something like this. Jakob has the right answer, i.e. use x = number(5).
However, that said, I wanted to try how it could be done in theory, and here's one solution in the form of a decorator:
import types
class number(object):
def __init__(self, value):
self.value = value
def replace_int(x):
if isinstance(x, int):
return number(x)
else:
return x
def custom_numbers(f):
code = f.func_code
consts = tuple(map(replace_int, code.co_consts))
new_code = types.CodeType(code.co_argcount, code.co_nlocals,
code.co_stacksize, code.co_flags,
code.co_code, consts, code.co_names,
code.co_varnames, code.co_filename,
code.co_name, code.co_firstlineno,
code.co_lnotab)
return types.FunctionType(new_code, f.func_globals, f.func_name)
Any function you decorate, will end up using your custom number class:
#custom_numbers
def test():
x = 5
print type(x)
>>> test()
<class '__main__.number'>
The decorator works by replacing integer constants from the function's code-object with instances of the custom class. However, since function.co_code and code.co_consts are both read-only attributes, we have to create new code and function objects with the altered values.
One caveat is, that the values are assumed to be constants, so new instances are not created for each invocation of the function. If you mutate the value, that new value will be reflected in each subsequent call of the function.
You would have to take advantage of Python's language services to compile the statement and then walk the AST replacing the objects as appropriate.
In fact, 5 is an instance of int, x is just pointing to it. All variables in Python are references to objects. Thus, when you write type(x) you get the type of the object which x holds a reference to, in this case it is int.
If you assign another value to x, say x = "string", x will hold a reference to that string object, and type(x) will return <type 'str'>.

Categories