Using mypy to type check and i cant figure out why this errors are happening [closed] - python

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
So, i using mypy to learn how to code in python using type check from the beginning. I'm using this code to train:
def stars(*args: int, **kwargs: float) -> None:
for arg in args:
print(arg)
for key, value in kwargs:
print(key, value)
stars(1.3,1.3)
I'm getting this typeerror:
learning_mypy.py:6: error: Unpacking a string is disallowed
learning_mypy.py:7: error: Cannot determine type of 'key'
learning_mypy.py:7: error: Cannot determine type of 'value'
learning_mypy.py:9: error: Argument 1 to "stars" has incompatible type "float"; expected "int"
learning_mypy.py:9: error: Argument 2 to "stars" has incompatible type "float"; expected "int"
Found 5 errors in 1 file (checked 1 source file)
So my questions are:
Why error mypy.py:6 is happening?
How do i define the type the value for key and value?
Why error mypy.py:9 is hapening?

If you do the below changes, mypy does not show anything.
def stars(*args: float, **kwargs: float) -> None:
for arg in args:
print(arg)
for key, value in kwargs.items():
print(key, value)
stars(1.3,1.3)
Why error mypy.py:6 is happening?
for key, value in kwargs: for this line, you should see the kwargs as a Python dictionary. If you iterate the kwargs in the for loop, it will iterate ONLY the key of the dictionary. Look at the below code.
d = {'1': 'one', '2': 'two', '3': 'three'}
for key in d:
print(key)
The output is:
1
2
3
If you want to print the values as well, you can use dict.items method.
d = {'1': 'one', '2': 'two', '3': 'three'}
for key, value in d.items():
print(key, value)
The output is:
1 one
2 two
3 three
or, you can access the value of the key over the dictionary.
for key in d:
print(key, d[key])
In line 6, since ONLY the keys are generated and also keys are a str; you are trying to unpack a string. Consider the below code:
var1, var2 = "test_variable"
This is exactly what your second for loop does.
How do i define the type the value for key and value?
You cannot define the type of the keys for kwargs but you can define the type of the values. (You already done it: kwargs: float)
Why error mypy.py:9 is hapening?
You defined the *args as int. But you passed float.
If you change *args: float, this error will be gone.

Related

How to change value dict out class [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I want to change dict value, but allert me a Error 'object does not support item assignment'
Full Code:
def __init__(self):
self.dict = dict()
def __getitem__(self, item):
return self.dict[item]
arr = SparseArray()
arr[0] = 1```
You to override __setitem__
def __setitem__(self, key, value):
self.dict[key] = value
Then you'll be able to assign a value using an index
# use of __setitem__
arr[0] = 1
arr["foo"] = 5
# use of __getitem__
print(arr[0]) # 1
print(arr["foo"]) # 5
Also avoid naming variable as built-in name like dict, at least you can use items or values if there is no real sense about the variable's content

How to remove a particular value from the list of values using Python

I am trying to remove the particular value from the list of key. I got Type error. I wrote function to add and remove the key. need to remove a particular value from the key
class my_dict(dict):
def add(self, key, value):
self.setdefault(key, []).append(value)
def remove_key(self, key):
del self[key]
#Error part
def remove_value(self,key,value):
for value in dict.values():
if v in value:
value.remove(v)
dict_obj = my_dict()
dict_obj.add('key1', 'value1')
dict_obj.add('key2', 'value2')
dict_obj.add('key1', 'value3')
print(dict_obj)
>>{'key1': ['value1', 'value3'], 'key2': ['value2']}
dict_obj.remove_value('key1','value3')
print(dict_obj)
My Out
TypeError: descriptor 'values' of 'dict' object needs an argument
Desired Output
>>{'key1': ['value1'], 'key2': ['value2']}
You've got a couple problems in:
def remove_value(self,key,value):
for value in dict.values():
if v in value:
value.remove(v)
You used dict.values(), not self.values(); the former is trying to call dict.values with no dict instance to operate on
You named two things value, and one replaces the other (while using v without ever naming anything v)
Minimal fix would be:
def remove_value(self,key,v): # Name argument v to match test and remove
for value in self.values(): # Call values on self
if v in value:
value.remove(v)
Slightly more readable fix (that would also limit removal to the specified key, which I'm guessing was the intent, since you receive a key argument) would be:
def remove_value(self, key, toremove):
try:
self[key].remove(toremove)
except (KeyError, ValueError):
pass
else:
if not self[key]:
del self[key]
Remove the try/except block if you want non-existent keys or values to raise KeyError or ValueError respectively. Remove the else block if you want to leave a key in place even if all values are removed.
you need to remove it from self[key].value if value in self[key]:
def remove_value(self,key,value):
if value in self.get(key, []):
self[key].remove(value)
But similar to your previous related question, this seems like you'd be better suited using defaultdict than trying to monkeypatch your own dict-like object.
from collections import defaultdict
mydict = defaultdict(list)
mydict['key1'].append('value1')
mydict['key1'].append('value3')
mydict['key2'].append('value2')
if 'value3' in mydict['key1']:
mydict['key1'].remove('value3')

How to pass "random" amount of variables not all of them exist

I have a method to validate input:
def validate_user_input(*args):
for item in args:
if not re.match('^[a-zA-Z0-9_-]+$', item):
And I'm calling it like this:
validate_user_input(var1, var2, ..., var7)
But those are generated from user input, and some of those can be missing. What would be the proper way to do that, without creating tons of if statements?
Variables are assigned from a json input like so, and json input might not have some of the needed properties:
var1 = request.json.get('var1')
I assume they are <class 'NoneType'>
Here's the error: TypeError: expected string or buffer
If your request.json object is a dict or dict-like you can just pass a default value as second argument to get
If I understand correctly you are generating var_ variables by request.json.get('var_') which will either return a string which you want to validate or None if the field was missing.
If this is the case then you can just add a special case to validate_user_input for a None value:
def validate_user_input(*args):
for item in args:
if item is None:
continue #this is acceptable, don't do anything with it
elif not re.match('^[a-zA-Z0-9_-]+$', item):
...
Or it may make more sense to store all of the values you are interested in in a dictionary:
wanted_keys = {'var1','var2','var3'}
## set intersection works in python3
present_keys = wanted_keys & response.json.keys()
## or for python 2 use a basic list comp
#present_keys = [key for key in response.json.keys() if key in wanted_keys]
actual_data = {key: response.json[key] for key in present_keys}
Then you would pass actual_data.values() as the argument list to validate_user_input.
If it really is possible that some var-variables are undefined when you call validate_user_input, why not just initialize them all (e.g. to the empty string '' so that your regex fails) before actually defining them?

What does replace = options.pop('replace', True) accomplish in this code? [duplicate]

class a(object):
data={'a':'aaa','b':'bbb','c':'ccc'}
def pop(self, key, *args):
return self.data.pop(key, *args)#what is this mean.
b=a()
print b.pop('a',{'b':'bbb'})
print b.data
self.data.pop(key, *args) ←------ why is there a second argument?
The pop method of dicts (like self.data, i.e. {'a':'aaa','b':'bbb','c':'ccc'}, here) takes two arguments -- see the docs
The second argument, default, is what pop returns if the first argument, key, is absent.
(If you call pop with just one argument, key, it raises an exception if that key's absent).
In your example, print b.pop('a',{'b':'bbb'}), this is irrelevant because 'a' is a key in b.data. But if you repeat that line...:
b=a()
print b.pop('a',{'b':'bbb'})
print b.pop('a',{'b':'bbb'})
print b.data
you'll see it makes a difference: the first pop removes the 'a' key, so in the second pop the default argument is actually returned (since 'a' is now absent from b.data).
So many questions here. I see at least two, maybe three:
What does pop(a,b) do?/Why are there a second argument?
What is *args being used for?
The first question is trivially answered in the Python Standard Library reference:
pop(key[, default])
If key is in the dictionary, remove it and return its value, else return default.
If default is not given and key is not in the dictionary, a KeyError is raised.
The second question is covered in the Python Language Reference:
If the form “*identifier” is present,
it is initialized to a tuple receiving
any excess positional parameters,
defaulting to the empty tuple. If the
form “**identifier” is present, it is
initialized to a new dictionary
receiving any excess keyword
arguments, defaulting to a new empty
dictionary.
In other words, the pop function takes at least two arguments. The first two get assigned the names self and key; and the rest are stuffed into a tuple called args.
What's happening on the next line when *args is passed along in the call to self.data.pop is the inverse of this - the tuple *args is expanded to of positional parameters which get passed along. This is explained in the Python Language Reference:
If the syntax *expression appears in
the function call, expression must
evaluate to a sequence. Elements from
this sequence are treated as if they
were additional positional arguments
In short, a.pop() wants to be flexible and accept any number of positional parameters, so that it can pass this unknown number of positional parameters on to self.data.pop().
This gives you flexibility; data happens to be a dict right now, and so self.data.pop() takes either one or two parameters; but if you changed data to be a type which took 19 parameters for a call to self.data.pop() you wouldn't have to change class a at all. You'd still have to change any code that called a.pop() to pass the required 19 parameters though.
def func(*args):
pass
When you define a function this way, *args will be array of arguments passed to the function. This allows your function to work without knowing ahead of time how many arguments are going to be passed to it.
You do this with keyword arguments too, using **kwargs:
def func2(**kwargs):
pass
See: Arbitrary argument lists
In your case, you've defined a class which is acting like a dictionary. The dict.pop method is defined as pop(key[, default]).
Your method doesn't use the default parameter. But, by defining your method with *args and passing *args to dict.pop(), you are allowing the caller to use the default parameter.
In other words, you should be able to use your class's pop method like dict.pop:
my_a = a()
value1 = my_a.pop('key1') # throw an exception if key1 isn't in the dict
value2 = my_a.pop('key2', None) # return None if key2 isn't in the dict
>>> def func(a, *args, **kwargs):
... print 'a %s, args %s, kwargs %s' % (a, args, kwargs)
...
>>> func('one', 'two', 'three', four='four', five='five')
a one, args ('two', 'three'), kwargs {'four': 'four', 'five': 'five'}
>>> def anotherfunct(beta, *args):
... print 'beta %s, args %s' % (beta, args)
...
>>> def func(a, *args, **kwargs):
... anotherfunct(a, *args)
...
>>> func('one', 'two', 'three', four='four', five='five')
beta one, args ('two', 'three')
>>>

How do you get a column name and row from table? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have to write a code where table is represented as dictionary, each key is the name of the column name and each value is the list of items in that column from top row to bottom.
I can use dictionary, list or whatever i want. So i decided to use dictionary
But when i test my code, I am getting this weird error :
>diction = {'a' : ['letter of a']}
>my_table = Table()
Traceback (most recent call last):
File "<string>", line 1, in <fragment>
builtins.TypeError: __init__() missing 3 required positional arguments: 'new_dict', 'coloumn_name', and 'coloumn_value'
Can someone help me with this?
class Table():
'''A class to represent a SQuEaL table'''
def __init__(self, new_dict, coloumn_name, coloumn_value):
self._new_dict = new_dict
self._key = coloumn_name
self._value = coloumn_value
def new_dictionary(self):
return self._new_dict
def get_coloumn_name(self):
return self._key
def get_coloumn_value(self):
return self._value
def set_dict(self, new_dict):
'''(Table, dict of {str: list of str}) -> NoneType
Populate this table with the data in new_dict.
The input dictionary must be of the form:
column_name: list_of_values
'''
# assign empty dictionary
self._new_dict = {}
# each key represents a coloumn name and each value is list of items
# that coloumn_name from top row to bottom(coloum_values)
self._new_dict += get_coloumn_name[self._key], get_coloumn_value[self._value]
return
You are getting this error because the __init__() function in your class requires 3 arguments - new_dict, coloumn_name, and coloumn_value - and you did not supply them.

Categories

Resources