2010-03-25 30 views
7

Tôi rất mới với Python và cố gắng tìm ra cách tạo đối tượng có giá trị có thể truy cập theo tên thuộc tính hoặc theo chỉ mục. Ví dụ, cách os.stat() trả về một stat_result hoặc pwd.getpwnam() trả về một struct_passwd.Cấu trúc có thể truy cập theo tên thuộc tính hoặc tùy chọn chỉ mục

Khi cố gắng tìm ra, tôi chỉ gặp các triển khai C của các loại trên. Không có gì đặc biệt trong Python. Cách bản địa Python để tạo ra loại đối tượng này là gì?

Tôi xin lỗi nếu điều này đã được bảo vệ rộng rãi rồi. Trong việc tìm kiếm câu trả lời, tôi phải bỏ lỡ một số khái niệm cơ bản không bao gồm việc tìm kiếm câu trả lời.

Trả lời

3

Bạn không thể sử dụng việc thực hiện tương tự như đối tượng kết quả của os.stat() và những người khác. Tuy nhiên Python 2.6 có một chức năng nhà máy mới tạo ra một kiểu dữ liệu tương tự được gọi là tuple có tên. Một tuple có tên là một tuple có các slot cũng có thể được giải quyết theo tên. Các tuple được đặt tên không nên yêu cầu bất kỳ bộ nhớ nhiều hơn, theo tài liệu, hơn một tuple thường xuyên, vì họ không có một từ điển mỗi trường hợp. Chữ ký chức năng nhà máy là:

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

Đối số đầu tiên chỉ định tên của các loại mới, số thứ hai là một chuỗi (không gian hoặc dấu phẩy tách ra) chứa các tên trường và cuối cùng, nếu verbose là đúng, chức năng nhà máy cũng sẽ in lớp được tạo ra.

Ví dụ

Giả sử bạn có một tuple chứa một tên người dùng và mật khẩu.Để truy cập vào tên người dùng bạn có được những item ở vị trí zero và mật khẩu được truy cập ở vị trí một:

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

Không có gì sai với mã này là nhưng tuple không phải là tự tài liệu. Bạn phải tìm và đọc tài liệu về vị trí của các trường trong tuple. Đây là nơi tuple được đặt tên có thể đến để giải cứu. Chúng ta có thể mã hóa lại các ví dụ trước như sau:

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 

Nếu bạn quan tâm về những gì mã trông giống như cho mới được tạo ra Credential kiểu bạn có thể thêm verbose = Đúng như danh sách đối số khi tạo kiểu, trong này trường hợp cụ thể chúng tôi nhận được kết quả như sau:

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

các tên tuple không chỉ cung cấp quyền truy cập vào các lĩnh vực theo tên mà còn chứa các chức năng helper như _make() chức năng mà giúp tạo ra một thể hiện ủy nhiệm từ một chuỗi hoặc có thể lặp lại. Ví dụ:

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

Các tài liệu thư viện python cho namedtuple có thêm thông tin và mã ví dụ, vì vậy tôi đề nghị bạn nên take a peek.

5

Python 2.6 giới thiệu collections.namedtuple để thực hiện việc này dễ dàng. Với các phiên bản Python cũ hơn, bạn có thể sử dụng named tuple recipe.

Trích dẫn trực tiếp từ các tài liệu:

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

một đối tượng có giá trị mà có thể truy cập hoặc theo tên thuộc tính, hoặc bằng chỉ số

Tôi không chắc chắn những gì bạn đang tìm thấy khó khăn về điều này.

Bộ sưu tập có thể truy cập được bằng chỉ mục thực hiện __getitem__.

Bộ sưu tập có thể truy cập theo tên được thực hiện __getattr__ (hoặc __getattribute__).

Bạn có thể triển khai cả hai mà không gặp bất kỳ sự cố nào. Hoặc, bạn có thể sử dụng namedtuple.

Để làm cho cuộc sống đơn giản hơn, bạn có thể mở rộng lớp tuple để bạn không phải triển khai __getitem__ của riêng mình. Hoặc bạn có thể xác định một lớp bình thường cũng có __getitem__, do đó bạn không phải gây rối với __getattr__.

Ví dụ

>>> 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 
Các vấn đề liên quan