This question already has answers here:
How do I use a keyword as a variable name?
(3 answers)
Closed 3 years ago.
Is there a way in python to override the definition of def?
Trying to create a method which will be named def, like this:
MyObject.def(arguments)
It's not possible. def is a keyword, so can't be overridden (unlike built-ins like max which can). Instead the convention is to add a trailing underscore:
class MyObject:
def def_():
pass
Although a better solution might be to expand the name: define
You can do something like this:
class A:
def x(self):
print('hi')
x.__name__ = 'def'
setattr(A, 'def', A.x)
delattr(A, 'x')
You won't be able to call the method literally:
>>> A().def()
...
A().def()
^
SyntaxError: invalid syntax
But the following will work:
>>> getattr(A(), 'def')()
'hi'
This is a terrible idea. def is a reserved keyword. While you can use the fact that class namespaces are dictionaries with string keys, please don't.
Related
This question already has answers here:
How do I use a keyword as a variable name?
(3 answers)
Closed 2 years ago.
I have stumbled upon the following syntax error with my Python3 interpreter:
class Class:
pass
a = Class()
a.from = 2
a.from = 2
^
SyntaxError: invalid syntax
Assignment of attributes that do not contain .from seem to be working fine:
a = Class()
a.fro = 2
print(a.__dict__)
{'fro': 2}
I understand that the standalone from statement is reserved for imports but struggle to understand why that would matter in the context of a class with the same key in its dict. Can someone explain why the interpreter complains at this point?
Simply because it's a reserved keyword that you can't use as an identifier.
The same issue would arise with e. g. x.in, x.for, x.import,...
Do I have to formally define a function before I can use it as an element of a dictionary?
def my_func():
print 'my_func'
d = {
'function': my_func
}
I would rather define the function inline. I just tried to type out what I want to do, but the whitespace policies of python syntax make it very hard to define an inline func within a dict. Is there any way to do this?
The answer seems to be that there is no way to declare a function inline a dictionary definition in python. Thanks to everyone who took the time to contribute.
Do you really need a dictionary, or just getitem access?
If the latter, then use a class:
>>> class Dispatch(object):
... def funcA(self, *args):
... print('funcA%r' % (args,))
... def funcB(self, *args):
... print('funcB%r' % (args,))
... def __getitem__(self, name):
... return getattr(self, name)
...
>>> d = Dispatch()
>>>
>>> d['funcA'](1, 2, 3)
funcA(1, 2, 3)
You could use a decorator:
func_dict = {}
def register(func):
func_dict[func.__name__] = func
return func
#register
def a_func():
pass
#register
def b_func():
pass
The func_dict will end up mapping using the entire name of the function:
>>> func_dict
{'a_func': <function a_func at 0x000001F6117BC950>, 'b_func': <function b_func at 0x000001F6117BC8C8>}
You can modify the key used by register as desired. The trick is that we use the __name__ attribute of the function to get the appropriate string.
Consider using lambdas, but note that lambdas can only consist of one expression and cannot contain statements (see http://docs.python.org/reference/expressions.html#lambda).
e.g.
d = { 'func': lambda x: x + 1 }
# call d['func'](2) will return 3
Also, note that in Python 2, print is not a function. So you have to do either:
from __future__ import print_function
d = {
'function': print
}
or use sys.stdout.write instead
d = {
'function': sys.stdout.write
}
Some functions can be easily 'inlined' anonymously with lambda expressions, e.g.:
>>> d={'function': lambda x : x**2}
>>> d['function'](5)
25
But for anything semi-complex (or using statements) you probably just should define them beforehand.
There is no good reason to want to write this using a dictionary in Python. It's strange and is not a common way to namespace functions.
The the Python philosophies that apply here are:
There should be one-- and preferably only one --obvious way to do it.
Combined with
Readability counts.
Doing it this way also makes things hard to understand and read for the typical Python user.
The good things the dictionary does in this case is map strings to functions and namespace them within a dictionary, but this functionality is already provided by both modules and classes and it's much easier to understand by those familiar with Python.
Examples:
Module method:
#cool.py
def cool():
print 'cool'
Now use the module like you would be using your dict:
import cool
#cool.__dict__['cool']()
#update - to the more correct idiom vars
vars(cool)['cool']()
Class method:
class Cool():
def cool():
print 'cool'
#Cool.__dict__['cool']()
#update - to the more correct idiom vars
vars(Cool)['cool']()
Edit after comment below:
argparse seems like a good fit for this problem, so you don't have to reinvent the wheel. If you do decide to implement it completely yourself though argparse source should give you some good direction. Anyways the sections below seem to apply to this use case:
15.4.4.5. Beyond sys.argv
Sometimes it may be useful to have an ArgumentParser parse arguments
other than those of sys.argv. This can be accomplished by passing a
list of strings to parse_args(). This is useful for testing at the
interactive prompt:
15.4.5.1. Sub-commands¶
ArgumentParser.add_subparsers()
Many programs split up their functionality into a number of sub-commands, for example, the svn program can invoke sub-commands
like svn checkout, svn update, and svn commit.
15.4.4.6. The Namespace object
It may also be useful to have an ArgumentParser assign attributes to
an already existing object, rather than a new Namespace object. This
can be achieved by specifying the namespace= keyword argument:
Update, here's an example using argparse
strategizer = argparse.ArgumentParser()
strat_subs = strategizer.add_subparsers()
math = strat_subs.add_parser('math')
math_subs = math.add_subparsers()
math_max = math_subs.add_parser('max')
math_sum = math_subs.add_parser('sum')
math_max.set_defaults(strategy=max)
math_sum.set_defaults(strategy=sum)
strategizer.parse_args('math max'.split())
Out[46]: Namespace(strategy=<built-in function max>)
strategizer.parse_args('math sum'.split())
Out[47]: Namespace(strategy=<built-in function sum>)
I would like to note the reasons I would recommend argparse
Mainly the requirement to use strings that represent options and sub options to map to functions.
It's dead simple (after getting past the feature filled argparse module).
Uses a Python Standard Library Module. This let's others familiar with Python grok what your doing without getting into implementation details, and is very well documented for those who aren't.
Many extra features could be taken advantage of out of the box (not the best reason!).
Using argparse and Strategy Pattern together
For the plain and simple implementation of the Strategy Pattern, this has already been answered very well.
How to write Strategy Pattern in Python differently than example in Wikipedia?
#continuing from the above example
class MathStudent():
def do_math(self, numbers):
return self.strategy(numbers)
maximus = strategizer.parse_args('math max'.split(),
namespace=MathStudent())
sumera = strategizer.parse_args('math sum'.split(),
namespace=MathStudent())
maximus.do_math([1, 2, 3])
Out[71]: 3
sumera.do_math([1, 2, 3])
Out[72]: 6
The point of inlining functions is to blur the distinction between dictionaries and class instances. In javascript, for example, this techinque makes it very pleasant to write control classes that have little reusability. Also, and very helpfully the API then conforms to the well-known dictionary protocols, being self explanatory (pun intended).
You can do this in python - it just doesn't look like a dictionary! In fact, you can use the class keyword in ANY scope (i.e. a class def in a function, or a class def inside of a class def), and it's children can be the dictonary you are looking for; just inspect the attributes of a definition as if it was a javascript dictionary.
Example as if it was real:
somedict = {
"foo":5,
"one_function":your method here,
"two_function":your method here,
}
Is actually accomplished as
class somedict:
foo = 5
#classmethod
def one_method(self):
print self.foo
self.foo *= 2;
#classmethod
def two_method(self):
print self.foo
So that you can then say:
somedict.foo #(prints 5)
somedict.one_method() #(prints 5)
somedict.two_method() #(prints 10)
And in this way, you get the same logical groupings as you would with your "inlining".
This question already has answers here:
Access to class attributes by using a variable in Python? [duplicate]
(2 answers)
Closed 7 years ago.
I got a class:
class thing:
def __init__(self, inp, inp2):
self.aThing = inp
self.bThing = inp2
def test(self, character):
print(self.eval(character+"Thing"))
(Important is the last line)
The test script would look like this:
x = thing(1, 2)
x.test("b")
Trying to run this it screams at me:
AttributeError: 'thing' object has no attribute 'eval'
Makes sense, so I tried this:
print(self.(eval(character+"Thing")))
Now its a Syntax error: .(
So is there a way Í could do this? And if not, is there a way to do this kind of case distinction without having to list all possible cases? (like using if-statements or the switch equivalent)
Oh, and I know that in this case I could just use a dictionary instead of a class, but that is not what I am searching for...
Your question is very broad and you're probably better off watching a talk on polymorphism and the super function(behaviour distinction without if) or python design patterns.
For the specific problem you posted you want to use getattr:
getattr(object, name[, default])
Return the value of the named
attribute of object. name must be a string. If the string is the name
of one of the object’s attributes, the result is the value of that
attribute. For example, getattr(x, 'foobar') is equivalent to
x.foobar. If the named attribute does not exist, default is returned
if provided, otherwise AttributeError is raised.
class thing:
def __init__(self, inp, inp2):
self.aThing = inp
self.bThing = inp2
def test(self, character):
print(getattr(self,character+"Thing"))
Example Demo
>>> t = thing(1, 2)
>>> t.test("a")
1
This question already has an answer here:
Why is it a syntax error to have an object attribute named "del", "return" etc?
(1 answer)
Closed 7 years ago.
I may have stumbled on an illegal variable name
pass = "Pass the monkey!"
print pass
Syntax error: invalid syntax
I'm aware that some keywords are verboten as variables.
Is there the Pythonic equivalent to JavaScript variable name validator?
You can test whether something is a keyword or not using the keyword module
>>> import keyword
>>> keyword.iskeyword("pass")
True
>>> keyword.iskeyword("not_pass")
False
https://docs.python.org/2/library/keyword.html
This module allows a Python program to determine if a string is a
keyword.
keyword.iskeyword(s)
Return true if s is a Python keyword.
Some variable names are illegal in Python because of it being a reserved word.
From the keywords section in the Python docs:
The following identifiers are used as reserved words, or keywords of
the language, and cannot be used as ordinary identifiers. They
must be spelled exactly as written here:
# Complete list of reserved words
and
del
from
not
while
as
elif
global
or
with
assert
else
if
pass
yield
break
except
import
print
class
exec
in
raise
continue
finally
is
return
def
for
lambda
try
True # Python 3 onwards
False # Python 3 onwards
None # Python 3 onwards
nonlocal # Python 3 onwards
async # in Python 3.7
await # in Python 3.7
So, you cannot use any of the above identifiers as a variable name.
This function will check if a name is a keyword in Python or one of Python built-in objects, which can be a function, a constant, a type or an exception class.
import keyword
def is_keyword_or_builtin(name):
return keyword.iskeyword(name) or name in dir(__builtins__)
While you can't use Python keywords as variable names, you are allowed to do it with Python built-ins though it's considered a bad practice so I will recommend to avoid it.
This question already has answers here:
How to print original variable's name in Python after it was returned from a function?
(13 answers)
Simpler way to create dictionary of separate variables?
(27 answers)
Closed 8 years ago.
For Python 2.7 I have a little utility for debugging:
def printvar(label, var):
print "%s:\n%s" % (label, pformat(var))
Often I call it like printvar("foo", foo).
Is it possible to simplify that a tiny bit and only pass in the variable, like printvar(foo), but still have it print the name of the variable? Using introspection or something?
You can't do that, but you can approximate the reverse: pass in only the label, and have it grab the actual value. Here's a quick version:
def printvar(label):
for frame in inspect.getouterframes(inspect.currentframe())[1:]:
local_vars = frame[0].f_locals
if label in local_vars:
print "%s:\n%s" % (label, frame[0].f_locals[label])
return
raise NameError("No such variable")
Then you can do this:
def foo():
x = 2
printvar('x')
>>> foo()
x:
2
This is, of course, very hacky business: the code looks through the local-variable namespaces of every stack frame in its call chain. Normally this kind of trickery is to be avoided, but for debugging purposes it can be useful in a pinch.