Sorry if I'm asking something dumb. I'm begginer btw.
Can I somehow place multiple variables in one variable, like:
login = "user"
enter = input(login + ">")
commandLogin = "login"
commandRegister = "register"
commandExit = "exit"
commandList = commandLogin, commandRegister, commandExit
while enter != commandList:
print("incorrect command!")
enter = input(login + ">")
Well, in the example you're already doing that.
The main correction is that you probably want while enter not in commandList
You can use an 'iterable', such as a tuple or a list. Check here: Python docs
So for your code you can use:
login = "user"
commandLogin = "login"
commandRegister = "register"
commandExit = "exit"
commandList = [commandLogin, commandRegister, commandExit]
enter = input(login + ">")
while enter not in commandList:
print("Incorrect command!")
enter = input(login + ">")
Sure. You can use a dictionary to put multiple variables in one variable:
>>> a={}
>>> a['first']='this is the first'
>>> a['second']='the second'
>>> a
{'first': 'this is the first', 'second': 'the second'}
>>> a['first']
'this is the first'
>>>
You can also create a class, an object of the class, and access attributes:
>>> class Empty():
... pass
...
>>> a = Empty()
>>> a.first = 'the first value'
>>> a.second = 'the second value'
>>> a
<__main__.Empty object at 0x7fceb005dbd0>
>>> a.first
'the first value'
>>> a.second
'the second value'
>>> a.third
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Empty' object has no attribute 'third'
>>>
In your example, you probably want to use a list:
>>> a = []
>>> a.append("first")
>>> a.append("second")
>>> a.append("third")
>>> a
['first', 'second', 'third']
>>>
But it's not really clear what you are trying to do in your example.
When you separate multiple variables by comma without any surrounding parenthesis, python creates a tuple for you:
a = 1
b = 2
c = 3
# implicit tuple
x = a, b, c
# equivalent, explicit tuple
x = (a, b, c)
Likewise, you can expand a tuple (or any iterable) into multiple variables:
# Expanding a tuple
x = (1, 2, 3)
a, b, c = x # a=1, b=2, c=3
# Expanding a list
x = [1, 2, 3]
a, b, c = x # a=1, b=2, c=3
# Expanding a dict (the keys are expanded into the new variables)
x = {'a': 1, 'b': 2}
a, b = x # a = 'a', b = 'b'
# Expanding an iterator
a, b = range(2) # a=0, b=1
The result of this is a tuple. A tuple is similar to a list but once a tuple is created, the values cannot be changed. The technique in the code is called tuple packing and essentially just creates a tuple.
So you can do it by many ways, i'll give you two of them!
You can always try to get to know some other ;)
You can do a list(changeable list) like this : colors = ["white", "blue", "red"].
Or you can do a tuple ( non-changeable list ( you can change the variable, but not the list itself )) like this : colors = ("white", "blue", "red")
Yes You can Place multiple Variable
but avoid it
https://www.geeksforgeeks.org/assigning-multiple-variables-in-one-line-in-python/
Related
Given three or more variables, I want to find the name of the variable with the min value.
I can get the min value from the list, and I can get the index within the list of the min value. But I want the variable name.
I feel like there's another way to go about this that I'm just not thinking of.
a = 12
b = 9
c = 42
cab = [c,a,b]
# yields 9 (the min value)
min(cab)
# yields 2 (the index of the min value)
cab.index(min(cab))
What code would yield 'b'?
The magic of vars prevents you from having to make a dictionary up front if you want to have things in instance variables:
class Foo():
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def min_name(self, names = None):
d = vars(self)
if not names:
names = d.keys()
key_min = min(names, key = (lambda k: d[k]))
return key_min
In action
>>> x = Foo(1,2,3)
>>> x.min_name()
'a'
>>> x.min_name(['b','c'])
'b'
>>> x = Foo(5,1,10)
>>> x.min_name()
'b'
Right now it'll crash if you pass an invalid variable name in the parameter list for min_name, but that's resolvable.
You can also update the dictionary and it's reflected in the source
def increment_min(self):
key = self.min_name()
vars(self)[key] += 1
Example:
>>> x = Foo(2,3,4)
>>> x.increment_min()
>>> x.a
3
You cannot get the name of the variable with the minimum/maximum value like this*, since as #jasonharper commented: cab is nothing more than a list containing three integers; there is absolutely no connection to the variables that those integers originally came from.
A simple workaround is to user pairs, like this:
>>> pairs = [("a", 12), ("b", 9), ("c", 42)]
>>> min(pairs)
('b', 9)
>>> min(pairs)[0]
'b'
See Green Cloak Guy's answer, but if you want to go for readability, I suggest following a similar approach to mine.
You'd have to get very creative for this to work, and the only solution I can think of is rather inefficient.
You can get the memory address of the data b refers to fairly easily:
>>> hex(id(b))
'0xaadd60'
>>> hex(id(cab[2]))
'0xaadd60'
To actually correspond that with a variable name, though, the only way to do that would be to look through the variables and find the one that points to the right place.
You can do this by using the globals() function:
# get a list of all the variable names in the current namespace that reference your desired value
referent_vars = [k for k,v in globals().items() if id(v) == id(cab[2])]
var_name = referent_vars[0]
There are two big problems with this solution:
Namespaces - you can't put this code in a function, because if you do that and then call it from another function, then it won't work.
Time - this requires searching through the entire global namespace.
The first problem could be alleviated by additionally passing the current namespace in as a variable:
def get_referent_vars(val, globals):
return [k for k,v in globals.items() if id(v) == id(val)]
def main():
a = 12
b = 9
c = 42
cab = [a, b, c]
var_name = get_referent_vars(
cab[cab.index(min(cab))],
globals()
)[0]
print(var_name)
# should print 'b'
a = munching mcdonalds
a,b,c = a.split(" ")
Traceback (most recent call last):
File "terminal.py", line 25, in <module>
a,b,c = a.split(" ")
ValueError: need more than 1 value to unpack
What code should I use instead if I want it to be either 2 or 3 words and still be able to print a?
If you don't actually need b or c, you could do something like:
>>> sentence = 'munching macdonalds'
>>> first, rest = sentence.split(' ', 1)
>>> first
'munching'
>>> rest
'macdonalds'
This uses the maxsplit parameter of str.split (see the docs) to limit to splitting on the first space.
You can then do e.g. if ' ' in rest: to determine whether the second part can be further split up.
If you're using Python 3, you can use the * notation to do the whole split, making first a string and rest a list:
>>> sentence = 'munching macdonalds'
>>> first, *rest = sentence.split(' ')
>>> first
'munching'
>>> rest
['macdonalds']
>>> sentence = 'foo bar baz'
>>> first, *rest = sentence.split(' ')
>>> first
'foo'
>>> rest
['bar', 'baz']
This version is easily repeatable and gives you values for all your variables on the left, in case you decide that you want to use them later (not just a). Note that it also does not modify the original list, so that it can be used as needed later.
def pad(iterable, length=0, padding=None):
li = list(iterable) # Generate new list from `iterable`.
li.extend([padding] * (length - len(li))) # Negative value generates empty list...
return li
sentence = 'munching mcdonalds'
a, b, c = pad(sentence.split(), 3)
assert (a, b, c) == ('munching', 'mcdonalds', None)
a, b, c, d = pad(range(3), 4)
assert (a, b, c, d) == (0, 1, 2, None)
a = pad(range(4), 3)
assert a == [0, 1, 2, 3]
Updated Answer
I thought about this after I made my initial post, and then myaut also pointed
out in a comment that it can be dangerous to generate this as a list. What if
we want to pad it to, say, 1E30 elements or so? So here's the function as a
generator.
def pad(iterable, length=0, padding=None):
for element in iterable:
yield element
for _ in range(length - len(iterable)):
yield padding
sentence = 'munching mcdonalds'
a, b, c = pad(sentence.split(), 3)
assert (a, b, c) == ('munching', 'mcdonalds', None)
a, b, c, d = pad(range(3), 4)
assert (a, b, c, d) == (0, 1, 2, None)
a = list(pad(range(4), 3))
assert a == [0, 1, 2, 3]
Thanks, myaut!
In Python 3, you can assign an arbitrary number of elements to the last item of a tuple unpacking.
>>> a, *b = "munching mcdonalds".split()
>>> a
munching
>>> b
['mcdonalds']
Well... If you really want it:
a, b, c = [value if index >= len(a.split(' ')) else a.split(' ')[index]
for index, value in enumerate([None] * 3)]
split() return a list. Therefore it should be use as one:
a = "munching mcdonalds"
b = a.split(" ")
>>>b
['munching', 'mcdonalds']
>>>b[0]
'munching'
>>>b[1]
'mcdonalds'
I'm having problems using copy.copy() and copy.deepcopy() and Python's scope. I call a function and a dictionary is passed as an argument. The dictionary copies a local dictionary but the dictionary does not retain the values that were copied.
def foo (A, B):
localDict = {}
localDict['name'] = "Simon"
localDict['age'] = 55
localDict['timestamp'] = "2011-05-13 15:13:22"
localDict['phone'] = {'work':'555-123-1234', 'home':'555-771-2190', 'mobile':'213-601-9100'}
A = copy.deepcopy(localDict)
B['me'] = 'John Doe'
return
def qua (A, B):
print "qua(A): ", A
print "qua(B): ", B
return
# *** MAIN ***
#
# Test
#
A = {}
B = {}
print "initial A: ", A
print "initial B: ", B
foo (A, B)
print "after foo(A): ", A
print "after foo(B): ", B
qua (A, B)
The copy.deepcopy works and within function "foo", dict A has the contents of localDict. But outside the scope of "foo", dict A is empty. Meanwhile, after being assigned a key and value, dict B retains the value after coming out of function 'foo'.
How do I maintain the values that copy.deepcopy() copies outside of function "foo"?
Ponder this:
>>> def foo(d):
... d = {1: 2}
...
>>> d = {3: 4}
>>> d
{3: 4}
>>> foo(d)
>>> d
{3: 4}
>>>
Inside foo, d = {1: 2} binds some object to the name d. This name is local, it does not modify the object d used to point to. On the other hand:
>>> def bar(d):
... d[1] = 2
...
>>> bar(d)
>>> d
{1: 2, 3: 4}
>>>
So this has nothing to do with your use of (deep)copy, it's just the way "variables" in Python work.
What's happening is that inside foo() you create a copy of B and assigns it to A, shadowing the empty dict you sent as an argument by reassigning a new object to the same name. Now inside the function you have a new dict called A, completely unrelated to the A outside in the global scope, and it gets garbage collected when the function ends, so actually nothing happens, only the 'me' key added to B.
If instead of:
A = copy.deepcopy(localDict)
You do something like this, it would work as you expect:
C = copy.deepcopy(localDict)
A.update(C)
But it seems like what you really want has nothing to do with the copy module and would be something like this:
def foo (A, B):
A['name'] = "Simon"
A['age'] = 55
A['timestamp'] = "2011-05-13 15:13:22"
A['phone'] = {'work':'555-123-1234', 'home':'555-771-2190', 'mobile':'213-601-9100'}
B['me'] = 'John Doe'
The behavior you are seeing isn't related to deepcopy(), you are reassigning the name A to a new value, and that assignment will not carry over unless you use the global keyword. The reason the changes to B are persistent is that you are modifying a mutable variable, here are two options for how you could get the behavior you want:
Instead of using localDict, just modify A:
def foo(A, B):
A['name'] = "Simon"
A['age'] = 55
A['timestamp'] = "2011-05-13 15:13:22"
A['phone'] = {'work':'555-123-1234', 'home':'555-771-2190', 'mobile':'213-601-9100'}
B['me'] = 'John Doe'
return
Use A.update(copy.deepcopy(localDict)) instead of A = copy.deepcopy(localDict):
def foo(A, B):
localDict = {}
localDict['name'] = "Simon"
localDict['age'] = 55
localDict['timestamp'] = "2011-05-13 15:13:22"
localDict['phone'] = {'work':'555-123-1234', 'home':'555-771-2190', 'mobile':'213-601-9100'}
A.update(copy.deepcopy(localDict))
B['me'] = 'John Doe'
return
Is there a way to group names together in python, to repeatedly assign to them en masse?
While we can do:
a,b,c = (1,2,3)
I would like to be able to do something like:
names = a,b,c
*names = (3,2,1) # this syntax doesn't work
a,b,c == (3,2,1) #=> True
Is there a built-in syntax for this? If not, I assume it would be possible with an object that overloads its assignment operator. In that case, is there an existing implementation, and would this concept have any unexpected failure modes?
The point is not to use the names as data, but rather to be able to use the actual names as variables that each refer to their own individual item, and to be able to use the list as a list, and to avoid code like:
a = 1
b = 2
c = 3
sequence = (a,b,c)
You should go one level up in your data abstraction. You are not trying to access the entries by their individual names -- you rather use names to denote the whole collection of values, so a simple list might be what you want.
If you want both, a name for the collection and names for the individual items, then a dictionary might be the way to go:
names = "a b c".split()
d = dict(zip(names, (1, 2, 3)))
d.update(zip(names, (3, 2, 1)))
If you need something like this repeatedly, you might want to define a class with the names as attributes:
class X(object):
def __init__(self, a, b, c):
self.update(a, b, c)
def update(self, a, b, c)
self.a, self.b, self.c = a, b, c
x = X(1, 2, 3)
x.update(3, 2, 1)
print x.a, x.b. x.c
This reflects that you want to block a, b and c to some common structure, but keep the option to access them individually by name.
This?
>>> from collections import namedtuple
>>> names = namedtuple( 'names', ['a','b','c'] )
>>> thing= names(3,2,1)
>>> thing.a
3
>>> thing.b
2
>>> thing.c
1
You should use a dict:
>>> d = {"a": 1, "b": 2, "c": 3}
>>> d.update({"a": 8})
>>> print(d)
{"a": 8, "c": 3, "b": 2}
I've realised that "exotic" syntax is probably unnecessary. Instead the following achieves what I wanted: (1) to avoid repeating the names and (2) to capture them as a sequence:
sequence = (a,b,c) = (1,2,3)
Of course, this won't allow:
*names = (3,2,1) # this syntax doesn't work
a,b,c == (3,2,1) #=> True
So, it won't facilitate repeated assignment to the same group of names without writing out those names repeatedly (except in a loop).
Well, you shouldn't do this, since it's potentially unsafe, but you can use the exec statement
>>> names = "a, b, c"
>>> tup = 1,2,3
>>> exec names + "=" + repr(tup)
>>> a, b, c
(1, 2, 3)
Python has such an elegant namespace system:
#!/usr/bin/env python
class GenericContainer(object):
def __init__(self, *args, **kwargs):
self._names = []
self._names.extend(args)
self.set(**kwargs)
def set(self, *args, **kwargs):
for i, value in enumerate(args):
self.__dict__[self._names[i]] = value
for name, value in kwargs.items():
if name not in self._names:
self._names.append(name)
self.__dict__[name] = value
def zip(self, names, values):
self.set(**dict(zip(names, values)))
def main():
x = GenericContainer('a', 'b', 'c')
x.set(1, 2, 3, d=4)
x.a = 10
print (x.a, x.b, x.c, x.d,)
y = GenericContainer(a=1, b=2, c=3)
y.set(3, 2, 1)
print (y.a, y.b, y.c,)
y.set(**dict(zip(('a', 'b', 'c'), (1, 2, 3))))
print (y.a, y.b, y.c,)
names = 'x', 'y', 'z'
y.zip(names, (4, 5, 6))
print (y.x, y.y, y.z,)
if __name__ == '__main__':
main()
Each instance of GenericContainer is an isolated namespace. IMHO it is better than messing with the local namespace even if you are programming under a pure procedural paradigm.
Not sure whether this is what you want...
>>> a,b,c = (1,2,3)
>>> names = (a,b,c)
>>> names
(1, 2, 3)
>>> (a,b,c) == names
True
>>> (a,b,c) == (1,2,3)
True
Is it possible in python to add a tuple as a value in a dictionary?
And if it is,how can we add a new value, then? And how can we remove and change it?
>>> a = {'tuple': (23, 32)}
>>> a
{'tuple': (23, 32)}
>>> a['tuple'] = (42, 24)
>>> a
{'tuple': (42, 24)}
>>> del a['tuple']
>>> a
{}
if you meant to use tuples as keys you could do:
>>> b = {(23, 32): 'tuple as key'}
>>> b
{(23, 32): 'tuple as key'}
>>> b[23, 32] = 42
>>> b
{(23, 32): 42}
Generally speaking there is nothing specific about tuples being in dictionary, they keep behaving as tuples.
Since tuples are immutable, you cannot add a value to the tuple. What you can do, is construct a new tuple from the current tuple and an extra value. The += operator does this for you, provided the left argument is a variable (or in this case a dictionary value):
>>> t = {'k': (1, 2)}
>>> t['k'] += (3,)
>>> t
{'k': (1, 2, 3)}
Regardless, if you plan on altering the tuple value, perhaps it's better to store lists? Those are mutable.
Edit: Since you updated your question†, observe the following:
>>> d = {42: ('name', 'date')}
>>> d[42][0] = 'name2'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
This happens because, as stated before, tuples are immutable. You cannot change them. If you want to change them, then in fact you'll have to create a new one. Thus:
>>> d[42] = ('name2', d[42][2])
>>> d
{42: ('name2', 'date')}
As a side note, you may want to use namedtuples. They work just like regular tuples, but allow you to refer to elements within the tuple by name:
>>> from collections import namedtuple
>>> Person = namedtuple('Person', 'name date')
>>> t = {42: Person('name', 'date')}
>>> t[42] = Person('name2', t[42].date)
>>> t
{42: Person(name='name2', date='date')}
†: Next time please edit your actual question. Do not post an answer containing only further questions. This is not a forum.
You can't change a tuple itself. You have to replace it by a different tuple.
When you use a list, you could also add values to it (changing the list itself) without need to replace it:
>> a = {'list': (23, 32)}
>> a
{'list': [23, 32]}
>> a['list'].append(99)
>> a
{'list': [23, 32, 99]}
In most cases, lists can be used as replacement for tuples (since as much I know they support all tuple functions -- this is duck typing, man!)
t1=('name','date')
t2=('x','y')
# "Number" is a String key!
d1={"Number":t1}
# Update the value of "Number"
d1["Number"] = t2
# Use a tuple as key, and another tuple as value
d1[t1] = t2
# Obtain values (getters)
# Can throw a KeyError if "Number" not a key
foo = d1["Number"]
# Does not throw a key error, t1 is the value if "Number" is not in the dict
d1.get("Number", t1)
# t3 now is the same as t1
t3 = d1[ ('name', 'date') ]
You updated your question again. Please take a look at Python dict docs. Python documentation is one of it's strong points! And play with the interpreter (python)on the command line! But let's continue.
initially key 0
d[0] = ('name', datetime.now())
id known
d1 = d[0]
del d[0]
name changed
tmp = d1
d1 = ( newname, tmp1 )
And please consider using a
class Person(object):
personIdCounter = 1
def __init__(self):
self.id = Person.personIdCounter
Person.personIdCounter += 1
self.name
self.date
then
persons = {}
person = Person()
persons[person.id] = person
person.name = "something"
persons[1].name = "something else"
That looks better than a tuple and models your data better.