Structure available by attribute name or index parameters

I am very new to Python and trying to figure out how to create an object that has values ​​available either by attribute name or by index. For example, the os.stat () method returns stat_result or pwd.getpwnam () returns struct_passwd.

In an attempt to figure this out, I only came across C implementations of the above types. Nothing special in Python. What is Python's own way to create such an object?

I apologize if this has already been widely covered. In search of an answer, I must miss some fundamental concept that excludes me from answering.

+7
python data-structures namedtuple
source share
3 answers

You cannot use the same implementation as the result object os.stat () and others. However, Python 2.6 has a new factory function that creates a similar data type called tuple. A named tuple is a tuple whose slots can also be addressed by name. A named tuple should not require more memory according to the documentation than a regular tuple, since they do not have a dictionary for each instance. Functional signature factory:

collections.namedtuple(typename, field_names[, verbose]) 

The first argument indicates the name of the new type, the second argument is a string (space or comma) containing the field names, and finally, if verbose is true, the factory function also prints the generated class.

Example

Suppose you have a tuple containing a username and password. To gain access to the username, you will get the item in position zero and access to the password in position 1:

 credential = ('joeuser', 'secret123') print 'Username:', credential[0] print 'Password:', credential[1] 

There is nothing wrong with this code, but the tuple is not self-documenting. You should find and read the documentation about placing fields in a tuple. It is here that the named motorcade can come to the rescue. We can recode the previous example as follows:

 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 

If you are interested in what the code looks like for the newly created Credential type, you can add verbose = True to the list of arguments when creating the type, in this particular case we get the following output:

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

A named tuple not only provides access to fields by name, but also contains helper functions, such as the _make () function, which helps you create a Credential instance from a sequence or iteration. For example:

 cred_tuple = ('joeuser', 'secret123') credential = Credential._make(cred_tuple) 

The python library documentation for namedtuple contains more information and code examples, so I suggest you take a look.

+3
source share

Python 2.6 introduced collections.namedtuple to make this easy. With older versions of Python, you can use the name of the tuple recipe .

Quoting directly from documents:

 >>> 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) >>> px + py # fields also accessible by name 33 >>> p # readable __repr__ with a name=value style Point(x=11, y=22) 
+5
source share

an object that has values ​​available either by attribute name or by index

I'm not sure what you find difficult.

The collection accessible by the index implements __getitem__ .

A collection accessible by name implements __getattr__ (or __getattribute__ ).

You can implement both without problems. Or you can use namedtuple .

To make life easier, you can extend the tuple class so you don't have to implement your own __getitem__ . Or you can define a regular class that also has __getitem__ , so you didn't have to bother with __getattr__ .

for example

 >>> 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) >>> fx 1 >>> f[0] 1 >>> f[1] 2 >>> f[2] 3 >>> fy 2 
0
source share

All Articles