7

私はPythonに非常に慣れていないので、属性名またはインデックスのいずれかでアクセスできる値を持つオブジェクトを作成する方法を理解しようとしています。たとえば、os.stat()がstat_resultを返す方法や、pwd.getpwnam()がstruct_passwdを返す方法です。

それを理解しようとして、私は上記のタイプのC実装にしか出くわしませんでした。特にPythonでは何もありません。この種のオブジェクトを作成するPythonネイティブの方法は何ですか?

これがすでに広くカバーされている場合は、お詫び申し上げます。答えを探す際に、答えを見つけることから私を排除しているいくつかの基本的な概念を見逃しているに違いありません。

4

3 に答える 3

5

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)
于 2010-03-25T02:01:22.873 に答える
3

os.stat() などの結果オブジェクトと同じ実装を使用することはできません。ただし、Python 2.6 には、名前付きタプルと呼ばれる同様のデータ型を作成する新しいファクトリ関数があります。名前付きタプルは、スロットを名前でアドレス指定できるタプルです。ドキュメントによると、名前付きタプルは、インスタンスごとの辞書を持たないため、通常のタプルよりも多くのメモリを必要としません。ファクトリ関数のシグネチャは次のとおりです。

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

最初の引数は新しい型の名前を指定し、2 番目の引数はフィールド名を含む文字列 (スペースまたはカンマで区切られた) であり、最後に verbose が true の場合、ファクトリ関数は生成されたクラスも出力します。

ユーザー名とパスワードを含むタプルがあるとします。ユーザー名にアクセスするには、0 の位置で項目を取得し、1 の位置でパスワードにアクセスします。

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

名前付きタプルは、名前によるフィールドへのアクセスを提供するだけでなく、シーケンスまたは反復可能オブジェクトから Credential インスタンスを作成するのに役立つ _make() 関数などのヘルパー関数も含みます。例えば:

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

namedtuple の Python ライブラリ ドキュメントには、より多くの情報とコード例があります

于 2010-03-25T06:21:57.860 に答える
0

属性名またはインデックスによってアクセス可能な値を持つオブジェクト

これについてあなたが何を難しいと思っているのかわかりません。

インデックスの実装によってアクセス可能なコレクション__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
于 2010-03-25T02:54:57.787 に答える