bit of an issue with a function I'm writing for adding and subtracting a value located within a class.
I'm trying to pass a value that I've read in from a csv to my add function. This value is a decimal value (e.g. 500.00) I've tried eliminating the trailing 0's to make it just 500, this didn't work either. I keep getting:
TypeError: add() takes exactly one argument (two given).
Even though I have a print statement confirming its only trying to pass in the 500.
Here's my function:
def add(amount):
self.total = self.total + amount
It's being called by v.add(i) Even if I set i to an arbitray integer value it still results in the same error. I am relatively inexperience with python, so perhaps there is something simple I'm missing here. Thanks.
class Myclass(object):
def __init__(self, total=0.):
self.total = total
def add(self, amount): # <= needs `self` parameter
self.total += amount
v = Myclass()
v.add(2.)
When you call an object method, it implicitly passes a reference to the object - so calling v.add(something) actually calls Myclass.add(v, something).
Voila - two parameters, when you told it to only expect one...
It sounds like you may have 2 issues:
the normal definition of a method presumes the 'self' argument
def add(self, amount):
you appear to be dealing with a string if you are trying to remove trailing zeros.
you may wish/need to convert the string value "500.00" to a floating point value
self.total = self.total + float(amount)
If you try to add a string to a number, Python will complain. You can see the type of an object being held in a variable using the type() function. E.g., you may wish to print the type of the 'amount' argument inside the add() method like this (for debugging):
print "the type of amount is", type(amount)
It will show you what you have (str, int, etc.)
(BTW it would probably be better style to convert it outside the method and have the method accept only numeric values for amount.)
Related
I was writing a print statement to test code.
But I realised I mistakenly had put a (self-defined) object (from a different class) in the {}.
I have already add the str method in the object to be able to call off print on it.
I tried to see if {print(thatobject)} would give me something.
When it didn't, I tried to read the document to understand what are the valid inputs for the {curly braces}. But couldn't understand it
Can someone explain what would be the valid inputs for the {curly braces} in a f string literal.
**Excuse me for using ppor terminology and just calling them "inputs". I hope you get what I mean (Variables, Function outputs, etc)
***I am aware that methods like len() can also be inserted in the {}.
class Player:
def __init__(self,name):
self.name = name
self.all_cards = []
def add_cards(self,new_cards):
'''
Will be able to add multiple cards or just a single
'''
if type(new_cards) == list:
self.all_cards.extend(new_cards)
else:
self.all_cards.append(new_cards)
def remove_one(self):
pass
def __str__(self):
return f"Player {self.name} has {len(self.all_cards)} cards. They are {print(self.all_cards)}"
in f-string's {curly braces} you can use any variables, class objects, executable expressions, function callings, etc. Anything can be used in brackets. You saw None on {print(self.all_cards)} because print function only returns None in python. If you want to print all_cards only remove that print method from it. Use like this {self.all_cards}.
As you can read on the official docs. Everything inside the {brackets} is expressions that are evaluated at runtime and then formatted to that string.
And if we elaborate your f-string working:
return f"Player {self.name} has {len(self.all_cards)} cards. They are {print(self.all_cards)}"
it will execute {self.name} get the variable value place it in that position, len(self.all_cards) len method is being executed and return the length of the self.all_cards list, {print(self.all_cards)} it will execute print method which only returned None.
And f-string will return like this after execution and formatting:
Player test has 0 cards. They are None
I'm trying to create a function that chains results from multiple arguments.
def hi(string):
print(string)<p>
return hi
Calling hi("Hello")("World") works and becomes Hello \n World as expected.
the problem is when I want to append the result as a single string, but
return string + hi produces an error since hi is a function.
I've tried using __str__ and __repr__ to change how hi behaves when it has not input. But this only creates a different problem elsewhere.
hi("Hello")("World") = "Hello"("World") -> Naturally produces an error.
I understand why the program cannot solve it, but I cannot find a solution to it.
You're running into difficulty here because the result of each call to the function must itself be callable (so you can chain another function call), while at the same time also being a legitimate string (in case you don't chain another function call and just use the return value as-is).
Fortunately Python has you covered: any type can be made to be callable like a function by defining a __call__ method on it. Built-in types like str don't have such a method, but you can define a subclass of str that does.
class hi(str):
def __call__(self, string):
return hi(self + '\n' + string)
This isn't very pretty and is sorta fragile (i.e. you will end up with regular str objects when you do almost any operation with your special string, unless you override all methods of str to return hi instances instead) and so isn't considered very Pythonic.
In this particular case it wouldn't much matter if you end up with regular str instances when you start using the result, because at that point you're done chaining function calls, or should be in any sane world. However, this is often an issue in the general case where you're adding functionality to a built-in type via subclassing.
To a first approximation, the question in your title can be answered similarly:
class add(int): # could also subclass float
def __call__(self, value):
return add(self + value)
To really do add() right, though, you want to be able to return a callable subclass of the result type, whatever type it may be; it could be something besides int or float. Rather than trying to catalog these types and manually write the necessary subclasses, we can dynamically create them based on the result type. Here's a quick-and-dirty version:
class AddMixIn(object):
def __call__(self, value):
return add(self + value)
def add(value, _classes={}):
t = type(value)
if t not in _classes:
_classes[t] = type("add_" + t.__name__, (t, AddMixIn), {})
return _classes[t](value)
Happily, this implementation works fine for strings, since they can be concatenated using +.
Once you've started down this path, you'll probably want to do this for other operations too. It's a drag copying and pasting basically the same code for every operation, so let's write a function that writes the functions for you! Just specify a function that actually does the work, i.e., takes two values and does something to them, and it gives you back a function that does all the class munging for you. You can specify the operation with a lambda (anonymous function) or a predefined function, such as one from the operator module. Since it's a function that takes a function and returns a function (well, a callable object), it can also be used as a decorator!
def chainable(operation):
class CallMixIn(object):
def __call__(self, value):
return do(operation(self, value))
def do(value, _classes={}):
t = type(value)
if t not in _classes:
_classes[t] = type(t.__name__, (t, CallMixIn), {})
return _classes[t](value)
return do
add = chainable(lambda a, b: a + b)
# or...
import operator
add = chainable(operator.add)
# or as a decorator...
#chainable
def add(a, b): return a + b
In the end it's still not very pretty and is still sorta fragile and still wouldn't be considered very Pythonic.
If you're willing to use an additional (empty) call to signal the end of the chain, things get a lot simpler, because you just need to return functions until you're called with no argument:
def add(x):
return lambda y=None: x if y is None else add(x+y)
You call it like this:
add(3)(4)(5)() # 12
You are getting into some deep, Haskell-style, type-theoretical issues by having hi return a reference to itself. Instead, just accept multiple arguments and concatenate them in the function.
def hi(*args):
return "\n".join(args)
Some example usages:
print(hi("Hello", "World"))
print("Hello\n" + hi("World"))
I've created the following example:
from typing import List, Sequence
class Circle:
pass
def foo(circle: Circle) -> Sequence[Circle]:
return_value: List[Circle] = [circle]
return return_value
def bar(circle: Circle) -> List[Sequence[Circle]]:
# Incompatible return value type (got "List[List[Circle]]", expected "List[Sequence[Circle]]")
return_value: List[List[Circle]] = [[circle]]
return return_value
Why is it okay to return a List[Circle] when it's expecting a Sequence[Circle], but not a List[List[Circle]] when it's expecting a List[Sequence[Circle]]?
More specifically, why is this not okay when the value is a return value? I think I understand why it's not okay as a parameter, but I don't get why this value is not accepted as a return value.
The docs give a great example displaying why Lists are invariant:
class Shape:
pass
class Circle(Shape):
def rotate(self):
...
def add_one(things: List[Shape]) -> None:
things.append(Shape())
my_things: List[Circle] = []
add_one(my_things) # This may appear safe, but...
my_things[0].rotate() # ...this will fail
Here, the idea is if you take your List[Subclass] and pass it to something that thinks it's a List[Superclass], the function can edit your List[Subclass] so that it contains Superclass elements, so it becomes a List[Superclass] after the function is run.
However, as a return value, I don't see why this is an issue. Once it exits that function, everyone will treat it as a List[Sequence[Circle]], which it is, so there should be no issues.
Once again, while typing up this question, I think I have figured out an answer to it.
Consider the following case:
from typing import List, Sequence
class Circle:
pass
def baz(circle_list_matrix: List[List[Circle]]) -> List[Sequence[Circle]]:
# Incompatible return value type (got "List[List[Circle]]", expected "List[Sequence[Circle]]")
return circle_list_matrix
Here, Mypy is absolutely right to raise the error, because the other functions that are using the circle_list_matrix may depend on it being a List[List[Circle]], but other functions afterwards may modify it to be a List[Sequence[Circle]].
In order to determine which case we're in, Mypy would have to keep track of when our variables were declared, and ensure that nothing ever depends on treating the return value as a List[List[Circle]] after the function returns (even though it is typed as such) before allowing us to use it as a return value.
(Note that treating it like a List[List[Circle]] before the function returns shouldn't be a bad thing, since it is a List[List[Circle]] at those points. Also if it was always treated like it was a List[Sequence[Circle]], then we could just type it as such with no problem. The question arises when something treats it like a List[List[Circle]], for example with circle_list_matrix[0].append(Circle()), so we have to type it as a List[List[Circle]] in order to do that operation, but then it's treated as a List[Sequence[Circle]] every single time after the function returns.)
The bottom line is that Mypy doesn't do that sort of analysis. So, in order to let Mypy know that this is okay, we should just cast it.
In other words, we know that the return value will never be used as a List[List[Circle]] again, so baz should be written as:
def baz(circle_list_matrix: List[List[Circle]]) -> List[Sequence[Circle]]:
# works fine
return cast(List[Sequence[Circle]], circle_list_matrix)
where cast is imported from typing.
The same casting technique can be applied to bar in the question code.
I am studying classes in python programming in jupyter notebooks and google colab.
I don't understand the results with respect to this class.
class employee_constructor():
def __init__(self,name,surname,salary):
self.name=name
self.surname=surname
self.salary=salary
def increasesalary(self,percentage):
self.salary=self.salary*(1+percentage/100)
def displayEmployee(self):
print('this employee is {} and gets {} dollars'.format(emp1.name,emp1.salary))
now I try to print out results:
emp1=employee_constructor('jose','ferro',1000)
emp2=employee_constructor('manolo','rod','1500')
emp1.displayEmployee
print('before increase',emp1.salary)
emp1.increasesalary(5)
emp1.increasesalary(5)
print('after increase',emp1.salary)
print(emp1.salary)
# this line does not give error and does nothing:
emp1.increasesalary
print(emp1.salary)
# this line gives error:
# increasesalary() missing 1 required positional argument: 'percentage'
emp1.increasesalary()
I don't understand why running the method without the parenthesis would not cause any error (actually the method is not run) whereas with the parenthesis (and not passing the neccesary variable through an error)
secondly, how can I avoid such kind of errors? i.e. if the user passes nothing assume vale zero
note:
this question explains init method and was proposed as solution. My question is related but is not answered there
I don't understand why running the method without the parenthesis would not cause any error (actually the method is not run) whereas with the parenthesis (and not passing the neccesary variable through an error)
When you refer a method (function in the context of an object, self is passed implicitly) by object.method the method object is returned. But to actually execute the function you need to call it i.e. use the parentheses.
For fun, save the returned method object as a variable and call that instead, you'll see that you're doing the same thing as they refer to the same object.
Now, when you called emp1.increasesalary(), you didn't pass the required argument percentage leading to the error. Note again, the self (object itself) is passed implicitly.
how can I avoid such kind of errors? i.e. if the user passes nothing assume vale zero
Make the argument a keyword argument with a default value of 0:
def increasesalary(self, percentage=0):
self.salary = self.salary * (1 + percentage / 100)
you can always use a funtion (without parenthesis) in python:
def f():
pass
print(f)
this will not call the function but just print out its memory location. so a line containing the function f itself is a valid python statement; but it does not call the function.
then: you need to use self and not emp1 in your displayEmployee(self) method:
def displayEmployee(self):
print('this employee is {} and gets {} dollars'.format(self.name, self.salary))
better:
def __str__(self):
return f"this employee is {self.name} and gets {self.salary} dollars"
then you can
print(emp1)
I'm creating a program with a class that has 3 input attributes. The program calls a function that creates many of these objects with their inputs being given based on some other criteria not important to this question.
As I further develop my program, I may want to add more and more attributes to the class. This means that I have to go and find all instances of the function I am using to create these objects, and change the input arguments.
For example, my program may have many of these:
create_character(blue, pizza, running)
where inputs correspond to character's favorite color, food, and activity. Later, I may want to add a fourth input, such as favorite movie, or possibly a fifth or sixth or ninety-ninth input.
Do professional programmers have any advice for structuring their code so that they don't have to go through and individually change each line that the create_character function is called so that it now has the new, correct number of inputs?
Find and replace seems fine, but this makes error possible, and also seems tedious. I'm anticipating calling this function at least 50 times.
I can think of a few options for how you could design your class to make easier to extend later new kinds of "favorite" things.
The first approach is to make most (or all) of the arguments optional. That is, you should specify a default value for each one (which might be None if there's not a real value that could apply as a default). This way, when you add an extra argument, the existing places that call the function without the new argument will still work, they'll just get the default value.
Another option would be to use a container (like a dictionary) to hold the values, rather than using a separate variable or argument for each one. For instance, in your example could represent the character's favorites using a dictionary like favorites = {'color': blue, 'food': pizza, 'activity': running} (assuming the those values are defined somewhere), and then you could pass the dictionary around instead of the separate items. If you use the get method of the dictionary, you can also make this type of design use default values (favorites.get('movie') will return None if you haven't updated the code that creates the dictionary to add a 'movie' key yet).
You can take advantage of argument/keyword argument unpacking to support dynamically-changing function parameters. And also factory function/classes that generate the function you need:
def create_character(required1, required2, *opt_args, **kwargs):
""" create_character must always be called with required1 and required2
but can receive *opt_args sequence that stores arbitrary number of
positional args. kwargs hold a dict of optional keyword args """
for i, pos_arg in enumerate(opt_args):
# pos_arg walks opt_args sequence
print "position: {}, value: {}".format(i+3, pos_arg)
for keyword, value in kwargs:
print "Keyword was: {}, Value was: {}".format(keyword, value)
pos_args = (1,2,3)
create_character('this is required','this is also required', *pos_args)
""" position: 3, value: 1
position: 4, value: 2
position: 5, value: 3 """
a_dict = {
'custom_arg1': 'custom_value1',
'custom_arg2': 'custom_value2',
'custom_arg3': 'custom_value3'
}
create_character('this is required','this is also required', **a_dict)
""" Keyword was: custom_arg2, value: custom_value2
Keyword was: custom_arg3, value: custom_value3
Keyword was: custom_arg1, value: custom_value1 """
I really like the list or dictionary input method, but it was still messy and allowed for the possibility of error. What I ended up doing was this:
I changed the class object to have no inputs. Favorites were first assigned with random, default, or unspecified options.
After the class object was created, I then edited the attributes of the object, as so:
self.favorite_movie = "unspecified"
self.favorite_activity = "unspecified"
new_character = (character())
new_character.favorite_movie = "Dr. Strangelove"
I think that the downside to this approach is that it should be slower than inputting the variables directly. The upside is that this is easy to change in the future. Perhaps when the program is finished, it will make more sense to then convert to #Blckknight 's method, and give the input as a list or dictionary.