Enum HOWTO¶
Zz000zz là tập hợp các tên tượng trưng được liên kết với các giá trị duy nhất. Chúng tương tự như các biến toàn cục, nhưng chúng cung cấp repr(), nhóm, an toàn kiểu và một số tính năng khác hữu ích hơn.
Chúng hữu ích nhất khi bạn có một biến có thể nhận một trong các giá trị được lựa chọn có giới hạn. Ví dụ: các ngày trong tuần:
>>> từ nhập enum Enum
>>> lớp Ngày trong tuần(Enum):
... MONDAY = 1
... TUESDAY = 2
... WEDNESDAY = 3
... THURSDAY = 4
... FRIDAY = 5
... SATURDAY = 6
... SUNDAY = 7
Hoặc có lẽ là các màu cơ bản của RGB:
>>> từ nhập enum Enum
>>> Màu lớp (Enum):
... RED = 1
... GREEN = 2
... BLUE = 3
Như bạn có thể thấy, việc tạo Enum cũng đơn giản như viết một lớp kế thừa từ chính Enum.
Ghi chú
Trường hợp thành viên Enum
Vì Enum được sử dụng để biểu thị các hằng số và giúp tránh các vấn đề về xung đột tên giữa các phương thức/thuộc tính của lớp mixin và tên enum, nên chúng tôi thực sự khuyên bạn nên sử dụng tên UPPER_CASE cho các thành viên và sẽ sử dụng kiểu đó trong các ví dụ của chúng tôi.
Tùy thuộc vào bản chất của enum, giá trị của thành viên có thể quan trọng hoặc không quan trọng, nhưng theo cách nào đó, giá trị đó có thể được sử dụng để có được thành viên tương ứng
>>> Ngày trong tuần(3)
<Ngày trong tuần.WEDNESDAY: 3>
Như bạn có thể thấy, repr() của một thành viên hiển thị tên enum, tên thành viên và giá trị. Zz001zz của một thành viên chỉ hiển thị tên enum và tên thành viên:
>>> in(Weekday.THURSDAY)
Ngày trong tuần.THURSDAY
Zz000zz của một thành viên liệt kê là enum mà nó thuộc về:
>>> gõ(Weekday.MONDAY)
<enum 'Ngày trong tuần'>
>>> isinstance(Weekday.FRIDAY, Weekday)
đúng
Các thành viên Enum có một thuộc tính chỉ chứa name:
>>> in(Weekday.TUESDAY.name)
TUESDAY
Tương tự như vậy, họ có một thuộc tính cho value:
>>> Ngày trong tuần.WEDNESDAY.value
3
Không giống như nhiều ngôn ngữ chỉ coi bảng liệt kê là cặp tên/giá trị, Python Enums có thể được thêm vào hành vi. Ví dụ: datetime.date có hai phương thức trả về ngày trong tuần: weekday() và isoweekday(). Sự khác biệt là một trong số chúng được tính từ 0-6 và cái còn lại từ 1-7. Thay vì tự mình theo dõi điều đó, chúng ta có thể thêm một phương thức vào enum Weekday để trích xuất ngày từ phiên bản date và trả về thành viên enum phù hợp:
@classmethod
def from_date(cls, date):
trả về cls(date.isoweekday())
Enum Weekday hoàn chỉnh bây giờ trông như thế này:
>>> lớp Ngày trong tuần(Enum):
... MONDAY = 1
... TUESDAY = 2
... WEDNESDAY = 3
... THURSDAY = 4
... FRIDAY = 5
... SATURDAY = 6
... SUNDAY = 7
... #
... @classmethod
... def from_date(cls, date):
... trả về cls(date.isoweekday())
Bây giờ chúng ta có thể tìm hiểu hôm nay là ngày gì! Quan sát:
>>> import datetime as dt
>>> Weekday.from_date(dt.date.today())
<Weekday.TUESDAY: 2>
Tất nhiên, nếu bạn đang đọc nó vào một ngày khác, thay vào đó bạn sẽ thấy ngày đó.
Enum Weekday này rất tuyệt nếu biến của chúng ta chỉ cần một ngày, nhưng nếu chúng ta cần nhiều ngày thì sao? Có thể chúng ta đang viết một hàm để sắp xếp công việc trong một tuần và không muốn sử dụng list -- chúng ta có thể sử dụng một loại Enum khác:
>>> từ cờ nhập enum
>>> lớp Ngày trong tuần(Cờ):
... MONDAY = 1
... TUESDAY = 2
... WEDNESDAY = 4
... THURSDAY = 8
... FRIDAY = 16
... SATURDAY = 32
... SUNDAY = 64
Chúng tôi đã thay đổi hai điều: chúng tôi được kế thừa từ Flag và các giá trị đều là lũy thừa của 2.
Giống như enum Weekday ban đầu ở trên, chúng ta có thể có một lựa chọn duy nhất:
>>> first_week_day = Weekday.MONDAY
>>> ngày_tuần_đầu tiên
<Ngày trong tuần.MONDAY: 1>
Nhưng Flag cũng cho phép chúng ta kết hợp nhiều thành viên thành một biến duy nhất:
>>> cuối tuần = Ngày trong tuần.SATURDAY | Ngày trong tuần.SUNDAY
>>> cuối tuần
<Weekday.SATURDAY|SUNDAY: 96>
Bạn thậm chí có thể lặp lại biến Flag
>>> cho ngày cuối tuần:
... in(ngày)
Ngày trong tuần.SATURDAY
Ngày trong tuần.SUNDAY
Được rồi, hãy sắp xếp một số công việc nhé:
>>> việc vặt_for_ethan = {
... 'cho mèo ăn': Weekday.MONDAY | Weekday.WEDNESDAY | Weekday.FRIDAY,
... 'làm bát': Weekday.TUESDAY | Ngày trong tuần.THURSDAY,
... 'trả lời các câu hỏi SO': Weekday.SATURDAY,
... }
Và một chức năng hiển thị công việc trong một ngày nhất định
>>> def show_chores(việc vặt, ngày):
... cho việc vặt, ngày trong chores.items():
... nếu ngày tính bằng ngày:
... in(việc vặt)
...
>>> show_chores(chores_for_ethan, Weekday.SATURDAY)
trả lời câu hỏi SO
Trong trường hợp giá trị thực tế của các thành viên không quan trọng, bạn có thể tiết kiệm cho mình một số công việc và sử dụng auto() cho các giá trị:
>>> từ tự động nhập enum
>>> lớp Ngày trong tuần(Cờ):
... MONDAY = tự động()
... TUESDAY = tự động()
... WEDNESDAY = tự động()
... THURSDAY = tự động()
... FRIDAY = tự động()
... SATURDAY = tự động()
... SUNDAY = tự động()
... WEEKEND = SATURDAY | SUNDAY
Quyền truy cập có lập trình vào các thành viên liệt kê và thuộc tính của họ¶
Đôi khi, việc truy cập các thành viên trong bảng liệt kê theo chương trình sẽ rất hữu ích (tức là các tình huống mà Color.RED sẽ không thực hiện được vì không biết màu chính xác tại thời điểm viết chương trình). Enum cho phép truy cập như vậy
>>> Màu sắc(1)
<Color.RED: 1>
>>> Màu sắc(3)
<Color.BLUE: 3>
Nếu bạn muốn truy cập các thành viên enum bằng name, hãy sử dụng quyền truy cập mục:
>>> Màu sắc['RED']
<Color.RED: 1>
>>> Màu sắc['GREEN']
<Color.GREEN: 2>
Nếu bạn có thành viên enum và cần name hoặc value
>>> thành viên = Color.RED
>>> thành viên.name
'RED'
>>> thành viên.value
1
Sao chép các thành viên và giá trị enum¶
Có hai thành viên enum có cùng tên là không hợp lệ:
>>> Hình dạng lớp (Enum):
... SQUARE = 2
... SQUARE = 3
...
Traceback (cuộc gọi gần đây nhất):
...
TypeError: 'SQUARE' đã được xác định là 2
Tuy nhiên, một thành viên enum có thể có những tên khác gắn liền với nó. Cho hai mục A và B có cùng giá trị (và A được xác định trước), B là bí danh của thành viên A. Tra cứu theo giá trị của giá trị A sẽ trả về thành viên A. Tra cứu theo tên của A sẽ trả về thành viên A. Tra cứu theo tên của B cũng sẽ trả về thành viên A:
>>> Hình dạng lớp (Enum):
... SQUARE = 2
... DIAMOND = 1
... CIRCLE = 3
... ALIAS_FOR_SQUARE = 2
...
>>> Shape.SQUARE
<Hình dạng.SQUARE: 2>
>>> Shape.ALIAS_FOR_SQUARE
<Shape.SQUARE: 2>
>>> Hình dạng(2)
<Shape.SQUARE: 2>
Ghi chú
Không được phép cố gắng tạo một thành viên có cùng tên với một thuộc tính đã được xác định (thành viên khác, một phương thức, v.v.) hoặc cố gắng tạo một thuộc tính có cùng tên với một thành viên.
Đảm bảo giá trị liệt kê duy nhất¶
Theo mặc định, bảng liệt kê cho phép nhiều tên làm bí danh cho cùng một giá trị. Khi hành vi này không được mong muốn, bạn có thể sử dụng trình trang trí unique()
>>> from enum import Enum, duy nhất
>>> @unique
... Lỗi lớp(Enum):
... ONE = 1
... TWO = 2
... THREE = 3
... FOUR = 3
...
Traceback (cuộc gọi gần đây nhất):
...
ValueError: tìm thấy các giá trị trùng lặp trong <enum 'Mistake'>: FOUR -> THREE
Sử dụng giá trị tự động¶
Nếu giá trị chính xác không quan trọng, bạn có thể sử dụng auto:
>>> from enum import Enum, auto
>>> Màu lớp (Enum):
... RED = tự động()
... BLUE = tự động()
... GREEN = tự động()
...
>>> [member.value cho thành viên trong Màu sắc]
[1, 2, 3]
The values are chosen by _generate_next_value_(), which can be
overridden:
>>> lớp AutoName(Enum):
... @staticmethod
... def _generate_next_value_(tên, bắt đầu, đếm, giá trị cuối cùng):
... trả lại tên
...
>>> lớp Thứ tự(AutoName):
... NORTH = tự động()
... SOUTH = tự động()
... EAST = tự động()
... WEST = tự động()
...
>>> [member.value cho thành viên theo thứ tự]
['NORTH', 'SOUTH', 'EAST', 'WEST']
Ghi chú
Phương thức _generate_next_value_() phải được xác định trước bất kỳ thành viên nào.
Lặp lại¶
Việc lặp lại các thành viên của một enum không cung cấp các bí danh:
>>> danh sách(Hình dạng)
[<Shape.SQUARE: 2>, <Shape.DIAMOND: 1>, <Shape.CIRCLE: 3>]
>>> danh sách(Ngày trong tuần)
[<Weekday.MONDAY: 1>, <Weekday.TUESDAY: 2>, <Weekday.WEDNESDAY: 4>, <Weekday.THURSDAY: 8>, <Weekday.FRIDAY: 16>, <Weekday.SATURDAY: 32>, <Weekday.SUNDAY: 64>]
Lưu ý rằng bí danh Shape.ALIAS_FOR_SQUARE và Weekday.WEEKEND không được hiển thị.
Thuộc tính đặc biệt __members__ là ánh xạ tên theo thứ tự chỉ đọc cho các thành viên. Nó bao gồm tất cả các tên được xác định trong bảng liệt kê, bao gồm cả bí danh:
>>> cho tên, thành viên trong Shape.__members__.items():
... tên, thành viên
...
('SQUARE', <Shape.SQUARE: 2>)
('DIAMOND', <Shape.DIAMOND: 1>)
('CIRCLE', <Shape.CIRCLE: 3>)
('ALIAS_FOR_SQUARE', <Shape.SQUARE: 2>)
Thuộc tính __members__ có thể được sử dụng để truy cập theo chương trình chi tiết vào các thành viên liệt kê. Ví dụ: tìm tất cả các bí danh:
>>> [tên cho tên, thành viên trong Shape.__members__.items() if member.name != name]
['ALIAS_FOR_SQUARE']
Ghi chú
Bí danh cho cờ bao gồm các giá trị có nhiều cờ được đặt, chẳng hạn như 3 và không có cờ nào được đặt, tức là 0.
So sánh¶
Các thành viên liệt kê được so sánh theo danh tính:
>>> Color.RED là Color.RED
đúng
>>> Color.RED là Color.BLUE
sai
>>> Color.RED không phải là Color.BLUE
đúng
So sánh có thứ tự giữa các giá trị liệt kê được hỗ trợ not. Enum members are not integers (but see IntEnum below):
>>> Color.RED < Color.BLUE
Traceback (cuộc gọi gần đây nhất):
Tệp "<stdin>", dòng 1, trong <module>
TypeError: '<' không được hỗ trợ giữa các phiên bản của 'Color' và 'Color'
So sánh bình đẳng được xác định mặc dù
>>> Color.BLUE == Color.RED
sai
>>> Color.BLUE != Color.RED
đúng
>>> Color.BLUE == Color.BLUE
đúng
So sánh với các giá trị không liệt kê sẽ luôn so sánh không bằng nhau (một lần nữa, IntEnum được thiết kế rõ ràng để hoạt động khác, xem bên dưới):
>>> Color.BLUE == 2
sai
Cảnh báo
Có thể tải lại các mô-đun - nếu mô-đun được tải lại chứa enum, chúng sẽ được tạo lại và các thành viên mới có thể không so sánh giống/bằng với các thành viên ban đầu.
Các thành viên được phép và thuộc tính của bảng liệt kê¶
Hầu hết các ví dụ trên đều sử dụng số nguyên cho các giá trị liệt kê. Việc sử dụng số nguyên rất ngắn gọn và tiện dụng (và được Functional API cung cấp theo mặc định), nhưng không được thực thi nghiêm ngặt. Trong phần lớn các trường hợp sử dụng, người ta không quan tâm giá trị thực của một bảng liệt kê là gì. Nhưng nếu giá trị is quan trọng thì bảng liệt kê có thể có giá trị tùy ý.
Bảng liệt kê là các lớp Python và có thể có các phương thức và phương thức đặc biệt như bình thường. Nếu chúng ta có bảng liệt kê này:
>>> Tâm trạng lớp (Enum):
... FUNKY = 1
... HAPPY = 3
...
... def mô tả (tự):
... # self là thành viên ở đây
... trả về self.name, self.value
...
... def __str__(tự):
... trả về 'str tùy chỉnh của tôi! {0}'.format(self.value)
...
... @classmethod
... def favorite_mood(cls):
... # cls đây là bảng liệt kê
... trả lại cls.HAPPY
...
Sau đó:
>>> Tâm trạng.favorite_mood()
<Tâm trạng.HAPPY: 3>
>>> Mood.HAPPY.describe()
('HAPPY', 3)
>>> str(Tâm trạng.FUNKY)
'str tùy chỉnh của tôi! 1'
Các quy tắc về những gì được phép như sau: tên bắt đầu và kết thúc bằng một dấu gạch dưới duy nhất được đặt trước bởi enum và không thể sử dụng được; tất cả các thuộc tính khác được xác định trong một bảng liệt kê sẽ trở thành thành viên của bảng liệt kê này, ngoại trừ các phương thức đặc biệt (__str__(), __add__(), v.v.), bộ mô tả (các phương thức cũng là bộ mô tả) và tên biến được liệt kê trong _ignore_.
Lưu ý: nếu bảng liệt kê của bạn xác định __new__() và/hoặc __init__(), mọi giá trị được cung cấp cho thành viên enum sẽ được chuyển vào các phương thức đó. Xem Planet để biết ví dụ.
Ghi chú
Phương thức __new__(), nếu được xác định, sẽ được sử dụng trong quá trình tạo thành viên Enum; sau đó nó được thay thế bằng __new__() của Enum, được sử dụng sau khi tạo lớp để tra cứu các thành viên hiện có. Xem Khi nào nên sử dụng __new__() so với __init__() để biết thêm chi tiết.
Phân lớp con Enum bị hạn chế¶
Một lớp Enum mới phải có một lớp enum cơ sở, tối đa một kiểu dữ liệu cụ thể và nhiều lớp mixin dựa trên object nếu cần. Thứ tự của các lớp cơ sở này là:
class EnumName([mix-in, ...,] [data-type,] base-enum):
vượt qua
Ngoài ra, việc phân lớp một bảng liệt kê chỉ được phép nếu bảng liệt kê không xác định bất kỳ thành viên nào. Vì vậy điều này bị cấm:
>>> lớp MoreColor(Color):
... PINK = 17
...
Traceback (cuộc gọi gần đây nhất):
...
TypeError: <enum 'MoreColor'> không thể mở rộng <enum 'Color'>
Nhưng điều này được cho phép:
>>> lớp Foo(Enum):
... def some_behavior(self):
... vượt qua
...
>>> Thanh lớp(Foo):
... HAPPY = 1
... SAD = 2
...
Việc cho phép phân lớp các enum xác định thành viên sẽ dẫn đến vi phạm một số bất biến quan trọng về loại và thể hiện. Mặt khác, sẽ hợp lý khi cho phép chia sẻ một số hành vi chung giữa một nhóm liệt kê. (Xem OrderedEnum để biết ví dụ.)
Hỗ trợ lớp dữ liệu¶
Khi kế thừa từ dataclass, __repr__() sẽ bỏ qua tên của lớp được kế thừa. Ví dụ:
>>> từ các lớp dữ liệu nhập lớp dữ liệu, trường
>>> @dataclass
... lớp CreatureDataMixin:
... kích thước: str
... chân: int
... đuôi: bool = field(repr=False, default=True)
...
>>> lớp Sinh vật(CreatureDataMixin, Enum):
... BEETLE = 'nhỏ', 6
... DOG = 'trung bình', 4
...
>>> Sinh vật.DOG
<Creature.DOG: size='trung bình', chân=4>
Sử dụng đối số dataclass() repr=False để sử dụng repr() tiêu chuẩn.
Thay đổi trong phiên bản 3.12: Chỉ các trường lớp dữ liệu được hiển thị trong vùng giá trị chứ không phải tên của lớp dữ liệu.
Ghi chú
Việc thêm trang trí dataclass() vào Enum và các lớp con của nó không được hỗ trợ. Nó sẽ không gây ra bất kỳ lỗi nào, nhưng nó sẽ tạo ra những kết quả rất lạ khi chạy, chẳng hạn như các thành viên bằng nhau
>>> @dataclass # don đừng làm điều này: nó chẳng có ý nghĩa gì cả
... Màu lớp (Enum):
... RED = 1
... BLUE = 2
...
>>> Color.RED là Color.BLUE
sai
>>> Color.RED == Color.BLUE # problem ở đây: chúng không được bằng nhau
đúng
dưa chua¶
Bảng liệt kê có thể được ngâm và giải nén:
>>> từ test.test_enum nhập trái cây
>>> từ bãi nhập dưa chua, tải
>>> Fruit.TOMATO rất nhiều(dumps(Fruit.TOMATO))
đúng
Áp dụng các hạn chế thông thường đối với việc tẩy chua: các enum có thể chọn được phải được xác định ở cấp cao nhất của mô-đun, vì việc giải nén yêu cầu chúng phải có thể được nhập từ mô-đun đó.
Ghi chú
Với giao thức dưa chua phiên bản 4, có thể dễ dàng chọn các enum được lồng trong các lớp khác.
Có thể sửa đổi cách các thành viên enum được chọn/bỏ chọn bằng cách xác định __reduce_ex__() trong lớp liệt kê. Phương thức mặc định là theo giá trị, nhưng các enum có giá trị phức tạp có thể muốn sử dụng theo tên:
>>> nhập enum
>>> lớp MyEnum(enum.Enum):
... __reduce_ex__ = enum.pickle_by_enum_name
Ghi chú
Không nên sử dụng tên theo cho cờ vì các bí danh không được đặt tên sẽ không được giải quyết.
Chức năng API¶
Lớp Enum có thể gọi được, cung cấp chức năng API sau:
>>> Động vật = Enum('Động vật', 'ANT BEE CAT DOG')
>>> Động vật
<enum 'Động vật'>
>>> Động vật.ANT
<Động vật.ANT: 1>
>>> danh sách(Động vật)
[<Animal.ANT: 1>, <Animal.BEE: 2>, <Animal.CAT: 3>, <Animal.DOG: 4>]
Ngữ nghĩa của API này giống với namedtuple. Đối số đầu tiên của lệnh gọi tới Enum là tên của bảng liệt kê.
Đối số thứ hai là source của tên thành viên liệt kê. Nó có thể là một chuỗi tên được phân tách bằng khoảng trắng, một chuỗi tên, một chuỗi gồm 2 bộ dữ liệu với các cặp khóa/giá trị hoặc ánh xạ (ví dụ: từ điển) tên thành giá trị. Hai tùy chọn cuối cùng cho phép gán giá trị tùy ý cho bảng liệt kê; những cái khác tự động gán số nguyên tăng dần bắt đầu bằng 1 (sử dụng tham số start để chỉ định giá trị bắt đầu khác). Một lớp mới bắt nguồn từ Enum được trả về. Nói cách khác, phép gán trên cho Animal tương đương với:
>>> lớp Động vật(Enum):
... ANT = 1
... BEE = 2
... CAT = 3
... DOG = 4
...
Lý do mặc định 1 là số bắt đầu chứ không phải 0 là vì 0 là False theo nghĩa boolean, nhưng theo mặc định, các thành viên enum đều đánh giá là True.
Các enum tẩy được tạo bằng API chức năng có thể phức tạp vì các chi tiết triển khai ngăn xếp khung được sử dụng để thử và tìm ra mô-đun liệt kê đang được tạo trong mô-đun nào (ví dụ: nó sẽ thất bại nếu bạn sử dụng chức năng tiện ích trong một mô-đun riêng biệt và cũng có thể không hoạt động trên IronPython hoặc Jython). Giải pháp là chỉ định rõ ràng tên mô-đun như sau
>>> Động vật = Enum('Động vật', 'ANT BEE CAT DOG', module=__name__)
Cảnh báo
Nếu module không được cung cấp và Enum không thể xác định nó là gì thì các thành viên Enum mới sẽ không thể chọn được; để giữ lỗi gần nguồn hơn, việc tẩy rửa sẽ bị vô hiệu hóa.
Trong một số trường hợp, giao thức dưa chua mới 4 cũng dựa vào __qualname__ được đặt ở vị trí mà dưa chua có thể tìm thấy lớp. Ví dụ: nếu lớp được cung cấp trong lớp SomeData trong phạm vi toàn cầu
>>> Động vật = Enum('Động vật', 'ANT BEE CAT DOG', qualname='SomeData.Animal')
Chữ ký đầy đủ là:
liệt kê(
value='NewEnumName',
tên=<...>,
*,
mô-đun='...',
tên quốc tế='...',
type=<lớp hỗn hợp>,
bắt đầu=1,
)
value: Lớp enum mới sẽ ghi gì làm tên của nó.
names: Các thành viên enum. Đây có thể là một chuỗi được phân tách bằng khoảng trắng hoặc bằng dấu phẩy (các giá trị sẽ bắt đầu từ 1 trừ khi có quy định khác):
'RED GREEN BLUE' | 'RED,GREEN,BLUE' | 'RED, GREEN, BLUE'
hoặc một trình lặp tên:
['RED', 'GREEN', 'BLUE']
hoặc một trình vòng lặp của các cặp (tên, giá trị):
[('CYAN', 4), ('MAGENTA', 5), ('YELLOW', 6)]
hoặc một bản đồ:
{'CHARTREUSE': 7, 'SEA_GREEN': 11, 'ROSEMARY': 42}
module: tên của mô-đun nơi có thể tìm thấy lớp enum mới.
qualname: có thể tìm thấy lớp enum mới trong mô-đun ở đâu.
type: gõ để trộn vào lớp enum mới.
start: số bắt đầu đếm nếu chỉ có tên được truyền vào.
Thay đổi trong phiên bản 3.5: Tham số start đã được thêm vào.
Bảng liệt kê dẫn xuất¶
IntEnum¶
Biến thể đầu tiên của Enum được cung cấp cũng là một lớp con của int. Các thành viên của IntEnum có thể được so sánh với số nguyên; bằng cách mở rộng, các bảng liệt kê số nguyên thuộc các loại khác nhau cũng có thể được so sánh với nhau
>>> từ nhập enum IntEnum
>>> Hình dạng lớp (IntEnum):
... CIRCLE = 1
... SQUARE = 2
...
>>> Yêu cầu lớp(IntEnum):
... POST = 1
... GET = 2
...
>>> Hình dạng == 1
sai
>>> Shape.CIRCLE == 1
đúng
>>> Shape.CIRCLE == Yêu cầu.POST
đúng
Tuy nhiên, chúng vẫn không thể so sánh với bảng liệt kê Enum tiêu chuẩn:
>>> Hình dạng lớp (IntEnum):
... CIRCLE = 1
... SQUARE = 2
...
>>> Màu lớp (Enum):
... RED = 1
... GREEN = 2
...
>>> Shape.CIRCLE == Color.RED
sai
Các giá trị IntEnum hoạt động giống như số nguyên theo những cách khác mà bạn mong đợi:
>>> int(Shape.CIRCLE)
1
>>> ['a', 'b', 'c'][Shape.CIRCLE]
'b'
>>> [i cho i trong phạm vi(Shape.SQUARE)]
[0, 1]
StrEnum¶
Biến thể thứ hai của Enum được cung cấp cũng là một lớp con của str. Các thành viên của StrEnum có thể được so sánh với các chuỗi; bằng cách mở rộng, các bảng liệt kê chuỗi thuộc các loại khác nhau cũng có thể được so sánh với nhau.
Added in version 3.11.
cờ quốc tế¶
Biến thể tiếp theo của Enum được cung cấp, IntFlag, cũng dựa trên int. Sự khác biệt giữa các thành viên IntFlag có thể được kết hợp bằng cách sử dụng các toán tử bitwise (&, |, ^, ~) và kết quả vẫn là thành viên IntFlag, nếu có thể. Giống như IntEnum, các thành phần IntFlag cũng là số nguyên và có thể được sử dụng ở bất cứ nơi nào sử dụng int.
Ghi chú
Bất kỳ hoạt động nào trên thành viên IntFlag ngoài các hoạt động khôn ngoan về bit sẽ mất tư cách thành viên IntFlag.
Các hoạt động khôn ngoan về bit dẫn đến giá trị IntFlag không hợp lệ sẽ mất tư cách thành viên IntFlag. Xem FlagBoundary để biết chi tiết.
Added in version 3.6.
Thay đổi trong phiên bản 3.11.
Lớp IntFlag mẫu:
>>> từ nhập enum IntFlag
>>> lớp Perm(IntFlag):
... R = 4
... W = 2
... X = 1
...
>>> Perm.R | Perm.W
<Perm.R|W: 6>
>>> Perm.R + Perm.W
6
>>> RW = Perm.R | Perm.W
>>> Perm.R trong RW
đúng
Cũng có thể đặt tên cho các kết hợp:
>>> lớp Perm(IntFlag):
... R = 4
... W = 2
... X = 1
... RWX = 7
...
>>> Perm.RWX
<Perm.RWX: 7>
>>> ~Perm.RWX
<Perm: 0>
>>> Perm(7)
<Perm.RWX: 7>
Ghi chú
Các kết hợp được đặt tên được coi là bí danh. Bí danh không hiển thị trong quá trình lặp lại nhưng có thể được trả về từ việc tra cứu theo giá trị.
Thay đổi trong phiên bản 3.11.
Một điểm khác biệt quan trọng khác giữa IntFlag và Enum là nếu không có cờ nào được đặt (giá trị là 0), thì đánh giá boolean của nó là False:
>>> Perm.R & Perm.X
<Perm: 0>
>>> bool(Perm.R & Perm.X)
sai
Bởi vì các thành viên IntFlag cũng là lớp con của int nên chúng có thể được kết hợp với chúng (nhưng có thể mất tư cách thành viên IntFlag:
>>> Perm.X | 4
<Perm.R|X: 5>
>>> Perm.X + 8
9
Ghi chú
Toán tử phủ định, ~, luôn trả về một thành viên IntFlag có giá trị dương:
>>> (~Perm.X).value == (Perm.R|Perm.W).value == 6
đúng
Các thành viên IntFlag cũng có thể được lặp lại:
>>> danh sách(RW)
[<Perm.R: 4>, <Perm.W: 2>]
Added in version 3.11.
Cờ¶
Biến thể cuối cùng là Flag. Giống như IntFlag, các thành viên Flag có thể được kết hợp bằng cách sử dụng các toán tử bitwise (&, |, ^, ~). Không giống như IntFlag, chúng không thể được kết hợp hoặc so sánh với bất kỳ bảng liệt kê Flag nào khác hoặc int. Mặc dù có thể chỉ định trực tiếp các giá trị nhưng bạn nên sử dụng auto làm giá trị và để Flag chọn một giá trị thích hợp.
Added in version 3.6.
Giống như IntFlag, nếu sự kết hợp của các thành viên Flag dẫn đến không có cờ nào được đặt thì đánh giá boolean là False:
>>> từ cờ nhập enum, tự động
>>> Màu lớp (Cờ):
... RED = tự động()
... BLUE = tự động()
... GREEN = tự động()
...
>>> Color.RED & Color.GREEN
<Màu sắc: 0>
>>> bool(Color.RED & Color.GREEN)
sai
Các cờ riêng lẻ phải có các giá trị là lũy thừa của hai (1, 2, 4, 8, ...), trong khi các tổ hợp cờ sẽ không:
>>> Màu lớp (Cờ):
... RED = tự động()
... BLUE = tự động()
... GREEN = tự động()
... WHITE = RED | BLUE | GREEN
...
>>> Color.WHITE
<Color.WHITE: 7>
Đặt tên cho điều kiện "không đặt cờ" không làm thay đổi giá trị boolean của nó:
>>> Màu lớp (Cờ):
... BLACK = 0
... RED = tự động()
... BLUE = tự động()
... GREEN = tự động()
...
>>> Color.BLACK
<Color.BLACK: 0>
>>> bool(Color.BLACK)
sai
Các thành viên Flag cũng có thể được lặp lại:
>>> tím = Color.RED | Màu.BLUE
>>> danh sách (màu tím)
[<Color.RED: 1>, <Color.BLUE: 2>]
Added in version 3.11.
Ghi chú
Đối với phần lớn mã mới, Enum và Flag được đặc biệt khuyến khích, vì IntEnum và IntFlag phá vỡ một số lời hứa về ngữ nghĩa của một bảng liệt kê (bằng cách có thể so sánh với các số nguyên và do đó có tính bắc cầu với các bảng liệt kê không liên quan khác). IntEnum và IntFlag chỉ nên được sử dụng trong trường hợp Enum và Flag không làm được; ví dụ: khi các hằng số nguyên được thay thế bằng các bảng liệt kê hoặc để có khả năng tương tác với các hệ thống khác.
Khác¶
Mặc dù IntEnum là một phần của mô-đun enum nhưng việc triển khai độc lập sẽ rất đơn giản:
lớp IntEnum(int, ReprEnum): # or Enum thay vì ReprEnum
vượt qua
Điều này chứng tỏ cách có thể định nghĩa các bảng liệt kê dẫn xuất tương tự; ví dụ: FloatEnum trộn trong float thay vì int.
Một số quy tắc:
Khi phân lớp
Enum, các loại kết hợp phải xuất hiện trước chính lớpEnumtheo chuỗi các cơ sở, như trong ví dụIntEnumở trên.Các loại kết hợp phải có thể phân lớp được. Ví dụ:
boolvàrangekhông thể phân lớp được và sẽ gây ra lỗi trong quá trình tạo Enum nếu được sử dụng làm loại kết hợp.Mặc dù
Enumcó thể có các thành viên thuộc bất kỳ loại nào, nhưng khi bạn kết hợp với một loại bổ sung, tất cả các thành viên phải có giá trị thuộc loại đó, ví dụ:intở trên. Hạn chế này không áp dụng cho các hỗn hợp chỉ thêm phương thức và không chỉ định loại khác.Khi một loại dữ liệu khác được trộn lẫn vào, thuộc tính
valuelà not the same với tư cách là thành viên enum, mặc dù nó tương đương và sẽ so sánh bằng nhau.Định dạng kiểu %:
%svà%rgọi lần lượt là__str__()và__repr__()của lớpEnum; các mã khác (chẳng hạn như%ihoặc%hcho IntEnum) coi thành viên enum là loại hỗn hợp của nó.Formatted string literals,
str.format()vàformat()sẽ sử dụng phương thức__str__()của enum.
Khi nào nên sử dụng __new__() so với __init__()¶
__new__() phải được sử dụng bất cứ khi nào bạn muốn tùy chỉnh giá trị thực của thành viên Enum. Bất kỳ sửa đổi nào khác có thể có trong __new__() hoặc __init__(), trong đó __init__() được ưu tiên.
Ví dụ: nếu bạn muốn chuyển một số mục cho hàm tạo nhưng chỉ muốn một trong số chúng là giá trị
>>> Tọa độ lớp(byte, Enum):
... """
... Phối hợp với các mã nhị phân có thể được lập chỉ mục bằng mã int.
... """
... def __new__(cls, giá trị, nhãn, đơn vị):
... obj = byte.__new__(cls, [giá trị])
... obj._value_ = giá trị
... obj.label = nhãn
... obj.unit = đơn vị
... trả lại đối tượng
... PX = (0, 'P.X', 'km')
... PY = (1, 'P.Y', 'km')
... VX = (2, 'V.X', 'km/s')
... VY = (3, 'V.Y', 'km/s')
...
>>> print(Phối hợp['PY'])
Tọa độ.PY
>>> in(Tọa độ(3))
Tọa độ.VY
Cảnh báo
Do not gọi super().__new__(), vì __new__ chỉ tra cứu là cái được tìm thấy; thay vào đó, hãy sử dụng kiểu dữ liệu trực tiếp.
Điểm tốt hơn¶
Tên __dunder__ và _sunder_ được hỗ trợ¶
Tên __dunder__ và _sunder_ được hỗ trợ có thể được tìm thấy trong Enum API documentation.
_Riêng__tên¶
Private names không được chuyển đổi thành thành viên enum mà vẫn giữ nguyên các thuộc tính bình thường.
Thay đổi trong phiên bản 3.11.
loại thành viên Enum¶
Các thành viên Enum là các phiên bản của lớp enum và thường được truy cập dưới dạng EnumClass.member. Trong một số trường hợp nhất định, chẳng hạn như viết hành vi enum tùy chỉnh, việc có thể truy cập trực tiếp một thành viên từ một thành viên khác là hữu ích và được hỗ trợ; tuy nhiên, để tránh xung đột tên giữa tên thành viên và thuộc tính/phương thức từ các lớp hỗn hợp, nên sử dụng tên viết hoa.
Thay đổi trong phiên bản 3.5.
Tạo các thành viên được trộn lẫn với các loại dữ liệu khác¶
Khi phân lớp các kiểu dữ liệu khác, chẳng hạn như int hoặc str, bằng Enum, tất cả các giá trị sau = đều được chuyển tới hàm tạo của kiểu dữ liệu đó. Ví dụ:
>>> class MyEnum(IntEnum): # help(int) -> int(x, base=10) -> số nguyên
... ví dụ = '11', 16 # so x='11' và base=16
...
>>> MyEnum.example.value # and hex(11) là...
17
Giá trị Boolean của các lớp và thành viên Enum¶
Các lớp Enum được trộn lẫn với các loại không phải Enum (chẳng hạn như int, str, v.v.) được đánh giá theo quy tắc của loại hỗn hợp; nếu không, tất cả các thành viên sẽ đánh giá là True. Để thực hiện đánh giá boolean của enum của riêng bạn tùy thuộc vào giá trị của thành viên, hãy thêm phần sau vào lớp của bạn
chắc chắn __bool__(tự):
trả về bool(self.value)
các lớp Enum với các phương thức¶
Nếu bạn cung cấp các phương thức bổ sung cho lớp con enum của mình, như lớp Planet bên dưới, thì các phương thức đó sẽ hiển thị trong dir() của thành viên chứ không phải của lớp:
>>> dir(Planet)
['EARTH', 'JUPITER', 'MARS', 'MERCURY', 'NEPTUNE', 'SATURN', 'URANUS', 'VENUS', '__class__', '__doc__', '__members__', '__module__']
>>> dir(Planet.EARTH)
['__class__', '__doc__', '__module__', 'mass', 'name', 'radius', 'surface_gravity', 'value']
Tổng hợp các thành viên của Flag¶
Việc lặp lại sự kết hợp của các thành viên Flag sẽ chỉ trả về các thành viên bao gồm một bit duy nhất:
>>> Màu lớp (Cờ):
... RED = tự động()
... GREEN = tự động()
... BLUE = tự động()
... MAGENTA = RED | BLUE
... YELLOW = RED | GREEN
... CYAN = GREEN | BLUE
...
>>> Màu sắc(3) # named kết hợp
<Color.YELLOW: 3>
>>> Màu(7) # not đặt tên kết hợp
<Color.RED|GREEN|BLUE: 7>
Flag và IntFlag chi tiết¶
Sử dụng đoạn mã sau cho ví dụ của chúng tôi
>>> Màu lớp (IntFlag):
... BLACK = 0
... RED = 1
... GREEN = 2
... BLUE = 4
... PURPLE = RED | BLUE
... WHITE = RED | GREEN | BLUE
...
những điều sau đây là đúng:
cờ một bit là hợp quy
cờ nhiều bit và 0 bit là bí danh
chỉ các cờ chuẩn được trả về trong quá trình lặp
>>> danh sách(Color.WHITE) [<Color.RED: 1>, <Color.GREEN: 2>, <Color.BLUE: 4>]
phủ định một cờ hoặc bộ cờ trả về một bộ cờ/cờ mới có giá trị nguyên dương tương ứng:
>>> Color.BLUE <Color.BLUE: 4> >>> ~Color.BLUE <Color.RED|GREEN: 3>
tên của các cờ giả được xây dựng từ tên các thành viên của họ:
>>> (Color.RED | Color.GREEN).name 'RED|GREEN' >>> lớp Perm(IntFlag): ... R = 4 ... W = 2 ... X = 1 ... >>> (Perm.R & Perm.W).name là Không có # effectively Perm(0) đúng
cờ nhiều bit, còn gọi là bí danh, có thể được trả về từ các hoạt động
>>> Color.RED | Màu.BLUE <Color.PURPLE: 5> >>> Màu(7) # or Màu(-1) <Color.WHITE: 7> >>> Màu sắc(0) <Color.BLACK: 0>
kiểm tra tư cách thành viên/ngăn chặn: các cờ có giá trị bằng 0 luôn được coi là được chứa:
>>> Color.BLACK trong Color.WHITE đúng
mặt khác, chỉ khi tất cả các bit của một cờ nằm trong cờ kia thì True mới được trả về
>>> Color.PURPLE trong Color.WHITE đúng >>> Color.GREEN trong Color.PURPLE sai
Có một cơ chế ranh giới mới kiểm soát cách xử lý các bit ngoài phạm vi/không hợp lệ: STRICT, CONFORM, EJECT và KEEP:
STRICT --> đưa ra một ngoại lệ khi có giá trị không hợp lệ
CONFORM --> loại bỏ mọi bit không hợp lệ
EJECT --> mất trạng thái Cờ và trở thành int bình thường với giá trị đã cho
KEEP --> giữ lại những bit thừa
giữ trạng thái Cờ và các bit bổ sung
các bit bổ sung không hiển thị trong lần lặp
các bit bổ sung sẽ hiển thị trong repr() và str()
Giá trị mặc định cho Flag là STRICT, mặc định cho IntFlag là EJECT và mặc định cho _convert_ là KEEP (xem ssl.Options để biết ví dụ về thời điểm cần KEEP).
Enums và Flags khác nhau như thế nào?¶
Enums có siêu dữ liệu tùy chỉnh ảnh hưởng đến nhiều khía cạnh của cả lớp Enum dẫn xuất và phiên bản (thành viên) của chúng.
Lớp liệt kê¶
Siêu dữ liệu EnumType chịu trách nhiệm cung cấp các phương thức __contains__(), __dir__(), __iter__() và các phương thức khác cho phép một người thực hiện mọi việc với lớp Enum không thành công trên một lớp điển hình, chẳng hạn như list(Color) hoặc some_enum_var in Color. EnumType chịu trách nhiệm đảm bảo rằng nhiều phương thức khác trên lớp Enum cuối cùng là chính xác (chẳng hạn như __new__(), __getnewargs__(), __str__() và __repr__()).
Lớp cờ¶
Cờ có chế độ xem mở rộng về bí danh: để hợp lệ, giá trị của cờ cần phải là giá trị lũy thừa hai chứ không phải tên trùng lặp. Vì vậy, ngoài định nghĩa bí danh Enum, một cờ không có giá trị (còn gọi là 0) hoặc có nhiều hơn một giá trị lũy thừa hai (ví dụ: 3) được coi là bí danh.
Thành viên Enum (còn gọi là phiên bản)¶
Điều thú vị nhất về các thành viên enum là họ là những người độc thân. EnumType tạo ra tất cả chúng trong khi nó đang tạo chính lớp enum, sau đó đặt một __new__() tùy chỉnh để đảm bảo rằng không có cái mới nào được khởi tạo bằng cách chỉ trả về các phiên bản thành viên hiện có.
Cờ thành viên¶
Các thành viên gắn cờ có thể được lặp lại giống như lớp Flag và chỉ các thành viên chuẩn mới được trả về. Ví dụ:
>>> danh sách (Màu)
[<Color.RED: 1>, <Color.GREEN: 2>, <Color.BLUE: 4>]
(Lưu ý rằng BLACK, PURPLE và WHITE không hiển thị.)
Đảo ngược thành viên cờ trả về giá trị dương tương ứng, thay vì giá trị âm --- ví dụ:
>>> ~Color.RED
<Color.GREEN|BLUE: 6>
Các thành viên cờ có độ dài tương ứng với số giá trị lũy thừa hai mà chúng chứa. Ví dụ:
>>> len(Color.PURPLE)
2
Sách dạy nấu ăn Enum¶
Mặc dù Enum, IntEnum, StrEnum, Flag và IntFlag dự kiến sẽ bao gồm phần lớn các trường hợp sử dụng nhưng chúng không thể bao gồm tất cả. Dưới đây là các công thức cho một số loại bảng liệt kê khác nhau có thể được sử dụng trực tiếp hoặc làm ví dụ để tạo bảng liệt kê của riêng bạn.
Bỏ qua các giá trị¶
Trong nhiều trường hợp sử dụng, người ta không quan tâm giá trị thực của một bảng liệt kê là gì. Có một số cách để định nghĩa kiểu liệt kê đơn giản này:
sử dụng các phiên bản của
autocho giá trịsử dụng các phiên bản của
objectlàm giá trịsử dụng chuỗi mô tả làm giá trị
sử dụng một bộ dữ liệu làm giá trị và một
__new__()tùy chỉnh để thay thế bộ dữ liệu bằng một giá trịint
Việc sử dụng bất kỳ phương pháp nào trong số này sẽ biểu thị cho người dùng rằng những giá trị này không quan trọng và cũng cho phép người dùng thêm, xóa hoặc sắp xếp lại các thành viên mà không cần phải đánh số lại các thành viên còn lại.
Sử dụng auto¶
Sử dụng auto sẽ trông như thế này:
>>> Màu lớp (Enum):
... RED = tự động()
... BLUE = tự động()
... GREEN = tự động()
...
>>> Color.GREEN
<Color.GREEN: 3>
Sử dụng object¶
Sử dụng object sẽ trông như thế này:
>>> class Color(Enum):
... RED = object()
... GREEN = object()
... BLUE = object()
...
>>> Color.GREEN
<Color.GREEN: <object object at 0x...>>
Đây cũng là một ví dụ điển hình về lý do tại sao bạn có thể muốn viết __repr__():
>>> Màu lớp (Enum):
... RED = đối tượng()
... GREEN = đối tượng()
... BLUE = đối tượng()
... def __repr__(self):
... return "<%s.%s>" % (self.__class__.__name__, self._name_)
...
>>> Color.GREEN
<Color.GREEN>
Sử dụng chuỗi mô tả¶
Sử dụng một chuỗi làm giá trị sẽ trông như sau:
>>> Màu lớp (Enum):
... RED = 'dừng lại'
... GREEN = 'đi'
... BLUE = 'quá nhanh!'
...
>>> Color.GREEN
<Color.GREEN: 'đi'>
Sử dụng __new__() tùy chỉnh¶
Sử dụng __new__() tự động đánh số sẽ trông như sau:
>>> lớp AutoNumber(Enum):
... chắc chắn __new__(cls):
... giá trị = len(cls.__members__) + 1
... obj = object.__new__(cls)
... obj._value_ = giá trị
... trả lại đối tượng
...
>>> Màu lớp (Số tự động):
... RED = ()
... GREEN = ()
... BLUE = ()
...
>>> Color.GREEN
<Color.GREEN: 2>
Để tạo một AutoNumber có mục đích chung hơn, hãy thêm *args vào chữ ký:
>>> lớp AutoNumber(Enum):
... def __new__(cls, *args): # this là thay đổi duy nhất so với ở trên
... giá trị = len(cls.__members__) + 1
... obj = object.__new__(cls)
... obj._value_ = giá trị
... trả lại đối tượng
...
Sau đó, khi bạn kế thừa từ AutoNumber, bạn có thể viết __init__ của riêng mình để xử lý mọi đối số bổ sung
>>> lớp Swatch(AutoNumber):
... def __init__(self, pantone='unknown'):
... self.pantone = pantone
... AUBURN = '3497'
... SEA_GREEN = '1246'
... BLEACHED_CORAL = () màu # New, chưa có mã Pantone!
...
>>> Swatch.SEA_GREEN
<Swatch.SEA_GREEN: 2>
>>> Swatch.SEA_GREEN.pantone
'1246'
>>> Swatch.BLEACHED_CORAL.pantone
'không xác định'
Ghi chú
Phương thức __new__(), nếu được xác định, sẽ được sử dụng trong quá trình tạo thành viên Enum; sau đó nó được thay thế bằng __new__() của Enum, được sử dụng sau khi tạo lớp để tra cứu các thành viên hiện có.
Cảnh báo
Do not gọi super().__new__(), vì __new__ chỉ tra cứu là cái được tìm thấy; thay vào đó, hãy sử dụng kiểu dữ liệu trực tiếp -- ví dụ::
obj = int.__new__(cls, giá trị)
Đã đặt hàngEnum¶
Một bảng liệt kê có thứ tự không dựa trên IntEnum và do đó duy trì các bất biến Enum bình thường (chẳng hạn như không thể so sánh với các bảng liệt kê khác):
>>> lớp OrderedEnum(Enum):
... def __ge__(bản thân, người khác):
... nếu self.__class__ là other.__class__:
... trả về self.value >= other.value
... trả về Chưa thực hiện
... def __gt__(bản thân, người khác):
... nếu self.__class__ là other.__class__:
... trả về self.value > other.value
... trả về Chưa thực hiện
... def __le__(bản thân, người khác):
... nếu self.__class__ là other.__class__:
... trả về self.value <= other.value
... trả về Chưa thực hiện
... def __lt__(bản thân, người khác):
... nếu self.__class__ là other.__class__:
... trả về self.value < other.value
... trả về Chưa thực hiện
...
>>> Lớp lớp (OrderedEnum):
... A = 5
... B = 4
... C = 3
... Đ = 2
... F = 1
...
>>> Lớp.C < Lớp.A
đúng
trùng lặpmiễn phíEnum¶
Xảy ra lỗi nếu tìm thấy giá trị thành viên trùng lặp thay vì tạo bí danh:
>>> lớp DuplicateFreeEnum(Enum):
... def __init__(self, *args):
... cls = self.__class__
... nếu có(self.value == e.value cho e trong cls):
... a = self.name
... e = cls(self.value).name
... tăng ValueError(
... "bí danh không được phép trong DuplicateFreeEnum: %r --> %r"
... %(a,e))
...
>>> Màu lớp (DuplicateFreeEnum):
... RED = 1
... GREEN = 2
... BLUE = 3
... GRENE = 2
...
Traceback (cuộc gọi gần đây nhất):
...
ValueError: bí danh không được phép trong DuplicateFreeEnum: 'GRENE' --> 'GREEN'
Ghi chú
Đây là một ví dụ hữu ích cho việc phân lớp Enum để thêm hoặc thay đổi các hành vi khác cũng như không cho phép các bí danh. Nếu thay đổi mong muốn duy nhất là không cho phép bí danh, thì bạn có thể sử dụng trình trang trí unique() để thay thế.
MultiValueEnum¶
Hỗ trợ có nhiều hơn một giá trị cho mỗi thành viên:
>>> lớp MultiValueEnum(Enum):
... def __new__(cls, value, *values):
... self = object.__new__(cls)
... self._value_ = giá trị
... cho v trong các giá trị:
... self._add_value_alias_(v)
... trở về chính mình
...
>>> lớp DType(MultiValueEnum):
... float32 = 'f', 8
... double64 = 'd', 9
...
>>> DType('f')
<DType.float32: 'f'>
>>> DType(9)
<DType.double64: 'd'>
hành tinh¶
Nếu __new__() hoặc __init__() được xác định, giá trị của thành viên enum sẽ được chuyển cho các phương thức đó
>>> lớp Hành tinh(Enum):
... MERCURY = (3.303e+23, 2.4397e6)
... VENUS = (4.869e+24, 6.0518e6)
... EARTH = (5.976e+24, 6.37814e6)
... MARS = (6.421e+23, 3.3972e6)
... JUPITER = (1.9e+27, 7.1492e7)
... SATURN = (5.688e+26, 6.0268e7)
... URANUS = (8.686e+25, 2.5559e7)
... NEPTUNE = (1.024e+26, 2.4746e7)
... def __init__(tự, khối lượng, bán kính):
... self.khối lượng = khối lượng # in kilôgam
... self.radius = bán kính # in mét
... @property
... def surface_Gravity(self):
... # universal hằng số hấp dẫn (m3 kg-1 s-2)
... G = 6,67300E-11
... return G * self.mass / (self.radius * self.radius)
...
>>> Planet.EARTH.value
(5.976e+24, 6378140.0)
>>> Planet.EARTH.surface_Gravity
9.802652743337129
Thời gian¶
Một ví dụ để hiển thị thuộc tính _ignore_ đang sử dụng:
>>> nhập ngày giờ dưới dạng dt
>>> Giai đoạn lớp(dt.timedelta, Enum):
... "khoảng thời gian khác nhau"
... _ignore_ = 'Giai đoạn i'
... Thời kỳ = vars()
... cho tôi trong phạm vi (367):
... Khoảng thời gian['day_%d' % i] = i
...
>>> danh sách(Thời gian)[:2]
[<Period.day_0: datetime.timedelta(0)>, <Period.day_1: datetime.timedelta(days=1)>]
>>> danh sách(Thời gian)[-2:]
[<Period.day_365: datetime.timedelta(days=365)>, <Period.day_366: datetime.timedelta(days=366)>]
Phân lớp EnumType¶
Mặc dù hầu hết các nhu cầu về enum có thể được đáp ứng bằng cách tùy chỉnh các lớp con Enum, bằng cách trang trí lớp hoặc các hàm tùy chỉnh, nhưng EnumType có thể được phân lớp để mang lại trải nghiệm Enum khác.