Я очень плохо знаком с Python, и пытающийся выяснить, как создать объект, который имеет значения, которые доступны или названием атрибута, или индексом. Например, путь os.stat () возвращает stat_result, или pwd.getpwnam () возвращает struct_passwd.
В попытке понять это, я только столкнулся с реализациями C вышеупомянутых типов. Ничто конкретно в Python. Что собственный компонент Python путь состоит в том, чтобы создать этот вид объекта?
Я приношу извинения, если это уже было широко покрыто. В поиске ответа я должен пропускать некоторое фундаментальное понятие, которое исключает меня из нахождения ответа.
Вы не можете использовать ту же реализацию, что и объект результата os.stat () и других. Однако в Python 2.6 есть новая фабричная функция, которая создает аналогичный тип данных, называемый именованным кортежем. Именованный кортеж - это кортеж, слоты которого также можно адресовать по имени. Именованный кортеж не должен требовать больше памяти, согласно документации, чем обычный кортеж, поскольку у них нет словаря для каждого экземпляра. Сигнатура фабричной функции:
collections.namedtuple(typename, field_names[, verbose])
Первый аргумент указывает имя нового типа, второй аргумент - это строка (разделенная пробелами или запятыми), содержащая имена полей и, наконец, если verbose истинно, фабричная функция также будет распечатайте сгенерированный класс.
Пример
Предположим, у вас есть кортеж, содержащий имя пользователя и пароль. Чтобы получить доступ к имени пользователя, вы получаете элемент в нулевой позиции, а пароль - в первой позиции:
credential = ('joeuser', 'secret123')
print 'Username:', credential[0]
print 'Password:', credential[1]
В этом коде нет ничего плохого, но кортеж не самодокументируется. Вы должны найти и прочитать документацию о расположении полей в кортеже. Здесь на помощь может прийти именованный кортеж. Мы можем перекодировать предыдущий пример следующим образом:
import collections
# Create a new sub-tuple named Credential
Credential = collections.namedtuple('Credential', 'username, password')
credential = Credential(username='joeuser', password='secret123')
print 'Username:', credential.username
print 'Password:', credential.password
Если вас интересует, как выглядит код для вновь созданного Credential-type, вы можете добавить verbose = True в список аргументов при создании типа, в этом конкретном случае мы получаем следующий вывод:
import collections
Credential = collections.namedtuple('Credential', 'username, password', verbose=True)
class Credential(tuple):
'Credential(username, password)'
__slots__ = ()
_fields = ('username', 'password')
def __new__(_cls, username, password):
return _tuple.__new__(_cls, (username, password))
@classmethod
def _make(cls, iterable, new=tuple.__new__, len=len):
'Make a new Credential object from a sequence or iterable'
result = new(cls, iterable)
if len(result) != 2:
raise TypeError('Expected 2 arguments, got %d' % len(result))
return result
def __repr__(self):
return 'Credential(username=%r, password=%r)' % self
def _asdict(t):
'Return a new dict which maps field names to their values'
return {'username': t[0], 'password': t[1]}
def _replace(_self, **kwds):
'Return a new Credential object replacing specified fields with new values'
result = _self._make(map(kwds.pop, ('username', 'password'), _self))
if kwds:
raise ValueError('Got unexpected field names: %r' % kwds.keys())
return result
def __getnewargs__(self):
return tuple(self)
username = _property(_itemgetter(0))
password = _property(_itemgetter(1))
Именованный кортеж не только обеспечивает доступ к полям по имени, но также содержит вспомогательные функции, такие как функция _make (), которая помогает создать экземпляр Credential из последовательности или итерации.Например:
cred_tuple = ('joeuser', 'secret123')
credential = Credential._make(cred_tuple)
В документации библиотеки Python для namedtuple есть дополнительная информация и примеры кода, поэтому я предлагаю вам взглянуть.
объект, значения которого доступны либо по имени атрибута, либо по индексу.
Я не уверен, что вы в этом затрудняете.
Коллекция, доступная по индексу, реализует __ getitem __
.
Коллекция, доступная по именам, реализует __ getattr __
(или __ getattribute __
).
Вы можете без проблем реализовать и то, и другое. Или вы можете использовать namedtuple
.
Чтобы упростить жизнь, вы можете расширить класс tuple
, чтобы вам не приходилось реализовывать свой собственный __ getitem __
. Или вы можете определить обычный класс, который также имеет __ getitem __
, чтобы вам не пришлось возиться с __ getattr __
.
Например
>>> class Foo( object ):
... def __init__( self, x, y, z ):
... self.x= x
... self.y= y
... self.z= z
... def __getitem__( self, index ):
... return { 0: self.x, 1: self.y, 2: self.z }[index]
...
>>> f= Foo(1,2,3)
>>> f.x
1
>>> f[0]
1
>>> f[1]
2
>>> f[2]
3
>>> f.y
2
Python 2.6 представил collections. namedtuple , чтобы упростить эту задачу. В более старых версиях Python вы можете использовать именованный рецепт кортежа .
Цитата непосредственно из документов:
>>> Point = namedtuple('Point', 'x y')
>>> p = Point(11, y=22) # instantiate with positional or keyword arguments
>>> p[0] + p[1] # indexable like the plain tuple (11, 22)
33
>>> x, y = p # unpack like a regular tuple
>>> x, y
(11, 22)
>>> p.x + p.y # fields also accessible by name
33
>>> p # readable __repr__ with a name=value style
Point(x=11, y=22)