Python высший порядок присваивания последовательности? - PullRequest
1 голос
/ 24 февраля 2012

Есть ли способ объединить имена в Python, чтобы повторно присвоить им массово ?

Пока мы можем сделать:

a,b,c = (1,2,3)

Я хотел бы иметь возможность сделать что-то вроде:

names = a,b,c

*names = (3,2,1) # this syntax doesn't work

a,b,c == (3,2,1) #=> True

Есть ли встроенный синтаксис для этого? Если нет, я предполагаю, что это было бы возможно с объектом, который перегружает его оператор присваивания. В таком случае, существует ли существующая реализация, и будет ли у этой концепции неожиданный режим отказа?

Смысл состоит не в том, чтобы использовать имена в качестве данных, а в том, чтобы иметь возможность использовать фактические имена в качестве переменных, каждая из которых ссылается на свой отдельный элемент, и чтобы иметь возможность использовать список в качестве списка и избегать код как:

a = 1
b = 2
c = 3

sequence = (a,b,c)

Ответы [ 7 ]

2 голосов
/ 24 февраля 2012

Вы должны подняться на один уровень выше в вашей абстракции данных.Вы не пытаетесь получить доступ к записям по их отдельным именам - вы скорее используете names для обозначения всей совокупности значений, поэтому вам может понадобиться простой список.

Если вы хотите и то, и другое,имя для коллекции и имен для отдельных предметов, тогда можно выбрать словарь:

names = "a b c".split()
d = dict(zip(names, (1, 2, 3)))
d.update(zip(names, (3, 2, 1)))

Если вам нужно что-то подобное несколько раз, вы можете определитькласс с именами в качестве атрибутов:

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

Это отражает то, что вы хотите заблокировать a, b и c в какой-либо общей структуре, но сохраняете возможность доступа к ним индивидуально по имени.

1 голос
/ 24 февраля 2012

Это?

>>> from collections import namedtuple
>>> names = namedtuple( 'names', ['a','b','c'] )

>>> thing= names(3,2,1)
>>> thing.a
3
>>> thing.b
2
>>> thing.c
1
1 голос
/ 24 февраля 2012

Я понял, что «экзотический» синтаксис, вероятно, не нужен.Вместо этого следующее достигает того, что я хотел: (1) избежать повторения имен и (2) захватить их как последовательность:

sequence = (a,b,c) = (1,2,3)

Конечно, это не позволит:

*names = (3,2,1) # this syntax doesn't work

a,b,c == (3,2,1) #=> True

Таким образом, это не облегчит повторное присвоение одной и той же группе имен без повторной записи этих имен (кроме как в цикле).

1 голос
/ 24 февраля 2012

Вы должны использовать dict:

>>> d = {"a": 1, "b": 2, "c": 3}
>>> d.update({"a": 8})
>>> print(d)
{"a": 8, "c": 3, "b": 2}
0 голосов
/ 24 февраля 2012

Python имеет такую ​​элегантную систему пространств имен:

#!/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()

Каждый экземпляр GenericContainer является изолированным пространством имен.ИМХО, это лучше, чем возиться с локальным пространством имен, даже если вы программируете с чисто процедурной парадигмой.

0 голосов
/ 24 февраля 2012

Ну, вы не должны этого делать, поскольку это потенциально небезопасно, но вы можете использовать выражение exec

>>> names = "a, b, c"
>>> tup = 1,2,3
>>> exec names + "=" + repr(tup)
>>> a, b, c
(1, 2, 3)
0 голосов
/ 24 февраля 2012

Не уверен, хочешь ли ты этого ...

>>> 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
...