I want this method to update a certain value, unless passed another value, which it should update instead. Here's an example of what I want to do:
def update_t(self,t=self.t):
"If nothing is passed, then the default parameter is the attribute self.t"
t=t+1
I get "self is not defined"
This is a related question:default value of parameter as result of instance method
...but since this value is updated, I can't have it be None. I also cant have t be an object, because that would give me an error (can't add object and int). Any ideas? Thanks.
Use an object that can be resolved. Such as None.
def update_t(self, t=None):
"If nothing is passed, then the default parameter is the attribute self.t"
if t is None:
self.t += 1
else:
t += 1
Note that this may not change the value passed to it since the local name may be rebound if the object doesn't have a __iadd__() method.
Related
What is the difference between when we use a variable as an attribute like self.message and when we use it as a parameter like message in a method:
def talk(self, message)
print("{} sad : {}".format(self.name, self.message))
def talk(self, message)
print("{} sad : {}".format(self.name, message))
A parameter is really just a variable. It is declared by the function signature, and it gets assigned one of the arguments as part of the function call process.
An attribute is not a variable at all. It is a part of an object, similar to an index inside []. It is accessed using dot notation.
In your code, both functions declare a message parameter, but only the second one uses it. The first function gets all its information from the self object instead of using its message parameter.
I have a Question class with a setter method as follows.
#tokens.setter
def tokens(self, param: list, use_type: bool = False) -> None:
if not isinstance(param, list):
raise TypeError('Question.tokens must be a list')
if use_type:
self._tokens = None # assign something
else:
self._tokens = None # assign something else
After instantiating an object of class Question, I am trying to set its' tokens as follows.
question = Question(query['id'])
question.tokens = tokens, True # tokens is a list of words
I want to pass tokens as param and True as use_type parameter for the tokens setter method.
But I am getting a TypeError here as the first parameter param is getting a tuple as parameter.
How can I pass a value for the second parameter, use_type here? What is the correct syntax?
Separating values by comma without enclosing then in square brackets - [] - in Python, actually creates a tuple, not a list.
In fact, due to dynamic typing in Python, it is not considered a good practice to check exactly for a "list", when any sequence, or even iterable, will work equally well.
The second thing is that properties are meant to enable a single argument passing. Only the param parameter in your function will be used - the second parameter, use_type will not be passed by the property mechanism.
That means you have to read your arguments explicitly inside your method code, and a little extra logic is needed so that use_type is actually optional.
Actually, if you want to parametrize the settings of tokens with more than an argument, my advice would be to, in this case, just use a plain setter method, instead of resorting to properties or other descriptors. This will cause less surprise for people viewing (or having to write) code that use this class and set .tokens:
class Question:
...
def __init__(self, ...):
self.token = ... # Plain, unguarded attribute
..
def set_token(self, value, use_type = None):
...
But if you really want a property that will accept a sequence, with the second value being optional. However, if you are really using typing annotations and enforcing then, you have to restrict your params to tuples (which fortunately is the data type created by Python when you just separate objects by , as is in your code)
class Question:
...
#token.setter
def token(self, params: typing.Tuple[typing.Any, typing.Optional[bool]):
"""params should be a 1-or-2 tuple, with the second item, if present
a bool indicating "use_type"
"""
# The operation bellow will raise TypeError
# if params is not a tuple, so no need for the explicit check -
# just let the error propagate
value, use_type, *_ = params + (False,)
# if only one item is passed, "False" ends up in "use_type".
# With 2 itens, the extra "False" is assigned to "_" indicating
# it should be disregarded (it is a Python convention for '_' as a variable name)
if use_type:
...
And with this your question.tokens = tokens, True expression will work, as will
question.tokens = tokens,, but not question.tokens = tokens - as in this case, the value is not a tuple; (if it is a tuple it will be incorrectly used inside the method body as is) - I will say again that this is a strange pattern, and an explicit setter method should be preferred.
I want to use the default of a parameter, but include its name in the call. I thought that setting the parameter to None would do that, but it doesn't.
For example:
def a(num=3):
print(num)
a(num=None) #returns "None", not "3" like I want it to.
How can I use the default of a named parameter while including it in the call? (Is it even possible?)
Just to explain why I would want to do something like this (since maybe it's a problem in my overall coding style):
I often times have code like this
def add(num, numToAdd=1):
return num+numToAdd
def addTwice(num, numToAdd=None):
for i in range(2):
num=add(num, numToAdd=numToAdd)
return num
addTwice(3) #throws an error instead of returning 5
What I want is for addTwice's numToAdd to always use the default of add's numToAdd, no matter what it is.
The reason: maybe later in the code I realize that it's better to add 2 as the default when executing add than it is to add 1.
So I change it to
def add(num, numToAdd=2):
return num+numToAdd
But, this won't help anything unless I can always specify in addTwice to use the default if it receives a default.
So, that's the rationale.
In other words: I'm having a function (the first function) call another function (the second function), and if the first function has to use a default value, I want it to default to being the default value on the second function. That way, I only have to change the default value on the second function (not every single function that calls it as well) in order to change the default functionality.
There's no built-in support to explicitly use the default value of a parameter. If you don't want to leave the parameter out at the call site, you'd have to retrieve the default value very manually:
import inspect
a(num=inspect.signature(a).parameters['num'].default)
which wouldn't be worth it in most cases.
def a(num=None):
if num is None:
num = 3
print(num)
a(num=None) # prints 3
a() # prints 3
... I guess ... maybe
alternatively to explain default params
def a(num=3):
print(num)
a(num=None) # prints None
a() # prints 3
No, you can't: that's a contradiction in terms. The default value is used if and only if you do not supply a value in the arguments list. If you supply a value, then the default cannot be used within the routine.
There is a great answer on how to do this (if you decide that the default-getting functionality I asked for is really what you want). But, I just wanted to point out that in practice I believe what I was trying to achieve is normally done with global variables.
That is, the usual way to do what I wanted to do is:
DEFAULT_NUM_TO_ADD = 1
def add(num, numToAdd=DEFAULT_NUM_TO_ADD):
return num+numToAdd
def addTwice(num, numToAdd=DEFAULT_NUM_TO_ADD):
for i in range(2):
num=add(num, numToAdd=numToAdd)
return num
addTwice(3) # returns 5
This allows me to quickly change the default, and the same default is used for both functions. It's explicit and very clear; it's pythonic.
I am confused in return type and value of__init__() in Python.
Does __init__() return value or else and what is return type of__init__()?
init doesn't and shouldn't return any thing other than None. The purpose of init, as its name says, is to initialize attributes.
You can actually try to return None in init but not returning anything would by default return None in Python.
While being treated specially - it's automagically called with the newly created instance at instanciation time -, __init__ is by itself just an ordinary Python function, so it implicitely returns None unless you try to explicitely return something else... But then you will find out (at call time) that it's not allowed to return anything than None, so you can safely assume it won't return anything else ;)
I have a python program that I am trying to add an optional argument to.
If the user doesn't enter anything then I want that value to default to 20. But, if they do enter a value, I will use their value. I wrote that into the program like so:
optionParse= argparse.ArgumentParser(description='Change Number of Locations')
optionParse.add_argument('-n', dest='userDefSize')
args=optionParse.parse_args()
if args.n:
sizeOfList=args.userDefSize
else:
sizeOfList=20
But for some reason it keeps saying:
AttributeError: 'Namespace' object has no attribute 'n'
What would be the issue here? Is my if statement written incorrectly?
To answer your first question, add_argument takes a parameter 'default' which will do what you want. See the documentation
optionParse.add_argument('-n', dest='userDefSize', default=20)
To answer your second question, the 'dest' parameter redefines where the value passed in is stored in the arg namespace. In this case you told argparse to store the value in args.userDefSize instead of args.n, so args.n doesn't exist.