পাইথনে আমি কীভাবে 'এনুম' উপস্থাপন করতে পারি?


1143

আমি মূলত একটি সি # বিকাশকারী, তবে আমি বর্তমানে পাইথনের একটি প্রকল্পে কাজ করছি।

পাইথনে আমি কীভাবে এনামের সমতুল্য প্রতিনিধিত্ব করতে পারি?

উত্তর:


2685

পিইপি 435 তে বর্ণিত হিসাবে পাইথন 3.4-এ এনামগুলি যুক্ত করা হয়েছে । এটি পাইপিতে 3.3, 3.2, 3.1, 2.7, 2.6, 2.5, এবং 2.4 এ ব্যাকপোর্ট করা হয়েছে।

আরও উন্নত এনাম কৌশলগুলির জন্য অ্যানুম লাইব্রেরিটি চেষ্টা করুন (২.7, ৩.৩++, একই লেখক হিসাবে enum34কোড পাইপ 2 এবং পাই 3 এর মধ্যে পুরোপুরি সামঞ্জস্যপূর্ণ নয়, উদাহরণস্বরূপ আপনার __order__পাইথন 2 এর প্রয়োজন হবে )।

  • ব্যবহার করতে enum34, করতে$ pip install enum34
  • ব্যবহার করতে aenum, করতে$ pip install aenum

ইনস্টল করা enum(কোনও সংখ্যা নেই) সম্পূর্ণ আলাদা এবং বেমানান সংস্করণ ইনস্টল করবে।


from enum import Enum     # for enum34, or the stdlib version
# from aenum import Enum  # for the aenum version
Animal = Enum('Animal', 'ant bee cat dog')

Animal.ant  # returns <Animal.ant: 1>
Animal['ant']  # returns <Animal.ant: 1> (string lookup)
Animal.ant.name  # returns 'ant' (inverse lookup)

বা সমতুল্য:

class Animal(Enum):
    ant = 1
    bee = 2
    cat = 3
    dog = 4

পূর্ববর্তী সংস্করণগুলিতে, এনামগুলি সম্পাদন করার একটি উপায় হ'ল:

def enum(**enums):
    return type('Enum', (), enums)

যা এর মতো ব্যবহৃত হয়:

>>> Numbers = enum(ONE=1, TWO=2, THREE='three')
>>> Numbers.ONE
1
>>> Numbers.TWO
2
>>> Numbers.THREE
'three'

আপনি এই জাতীয় কিছু দিয়ে সহজেই স্বয়ংক্রিয়ভাবে গণনা সমর্থন করতে পারেন:

def enum(*sequential, **named):
    enums = dict(zip(sequential, range(len(sequential))), **named)
    return type('Enum', (), enums)

এবং এর মতো ব্যবহৃত:

>>> Numbers = enum('ZERO', 'ONE', 'TWO')
>>> Numbers.ZERO
0
>>> Numbers.ONE
1

মানগুলিকে আবার নামগুলিতে রূপান্তর করার জন্য সমর্থনটি এইভাবে যুক্ত করা যেতে পারে:

def enum(*sequential, **named):
    enums = dict(zip(sequential, range(len(sequential))), **named)
    reverse = dict((value, key) for key, value in enums.iteritems())
    enums['reverse_mapping'] = reverse
    return type('Enum', (), enums)

এটি সেই নামের সাথে যে কোনও কিছু ওভাররাইট করে তবে এটি আপনার এনামগুলিকে আউটপুট সরবরাহ করার জন্য কার্যকর। যদি বিপরীত ম্যাপিং উপস্থিত না থাকে তবে এটি কীয়ারকে ছুঁড়ে ফেলবে। প্রথম উদাহরণ সহ:

>>> Numbers.reverse_mapping['three']
'THREE'

1
আমি বুঝতে সক্ষম হচ্ছিলাম না কেন তারা এনওয়ার (* অনুক্রমিক, ** নাম) পদ্ধতিতে কাওয়ার্গস (** নামকরণ) পাস করলেন? দয়া করে ব্যাখ্যা করুন। Kwargs ছাড়াও এটি কাজ করবে। আমি এটি পরীক্ষা করেছিলাম।
Seenu এস

পাইথন 3 এর
এনাম

**namedপুরানো সংস্করণগুলির জন্য এনাম ফাংশনটিতে ভার্ কোয়ার্গস ( ) হ'ল কাস্টম মানগুলি সমর্থন করা:enum("blue", "red", "green", black=0)
এরিক আরাউজো ২

822

পিইপি 435 এর আগে পাইথনের সমতুল্য ছিল না তবে আপনি নিজের প্রয়োগ করতে পারেন।

নিজেই, আমি এটিকে সরল রাখতে পছন্দ করি (আমি নেটে কিছু মারাত্মক জটিল উদাহরণ দেখেছি), এরকম কিছু ...

class Animal:
    DOG = 1
    CAT = 2

x = Animal.DOG

পাইথন ৩.৪ ( পিইপি 435 ) এ আপনি এনামকে বেস ক্লাস করতে পারেন । পিইপিতে বর্ণিত এটি আপনাকে অতিরিক্ত কিছু কার্যকারিতা দেয় of উদাহরণস্বরূপ, enum সদস্যদের পূর্ণসংখ্যার থেকে স্বতন্ত্র, এবং তারা একটি দ্বারা গঠিত nameএবং একটি value

class Animal(Enum):
    DOG = 1
    CAT = 2

print(Animal.DOG)
# <Animal.DOG: 1>

print(Animal.DOG.value)
# 1

print(Animal.DOG.name)
# "DOG"

আপনি যদি মানগুলি টাইপ করতে না চান তবে নিম্নলিখিত শর্টকাটটি ব্যবহার করুন:

class Animal(Enum):
    DOG, CAT = range(2)

Enumবাস্তবায়নগুলি তালিকায় রূপান্তরিত হতে পারে এবং পুনরাবৃত্ত হয় । এর সদস্যদের আদেশ হ'ল ঘোষণার আদেশ এবং তাদের মানগুলির সাথে কোনও সম্পর্ক নেই। উদাহরণ স্বরূপ:

class Animal(Enum):
    DOG = 1
    CAT = 2
    COW = 0

list(Animal)
# [<Animal.DOG: 1>, <Animal.CAT: 2>, <Animal.COW: 0>]

[animal.value for animal in Animal]
# [1, 2, 0]

Animal.CAT in Animal
# True

51
না, এটি একটি শ্রেণি পরিবর্তনশীল।
জর্জি স্কলি

246
পাইথন ডিফল্টরূপে গতিশীল। পাইথনের মতো ভাষায় সংকলন-সময় সুরক্ষা কার্যকর করার কোনও বৈধ কারণ নেই, বিশেষত যখন কিছুই নেই। এবং অন্য একটি জিনিস ... একটি ভাল নিদর্শন এটি তৈরি করা হয়েছে সেই প্রসঙ্গে কেবল ভাল। আপনি যে সরঞ্জামগুলি ব্যবহার করছেন তার উপর নির্ভর করে একটি ভাল প্যাটার্নও ছাড়ানো বা সম্পূর্ণ অকেজো হতে পারে।
আলেকজান্দ্রু নেদেল্কু

20
@ লংপোক যদি আপনার 100 টি মান থাকে তবে আপনি অবশ্যই কিছু ভুল করছেন;) আমি আমার এনামগুলির সাথে সংযুক্ত নম্বর পছন্দ করি ... তারা লিখতে সহজ (বনাম স্ট্রিং), সহজেই একটি ডাটাবেসে স্থির থাকতে পারে এবং এর সাথে সামঞ্জস্যপূর্ণ সি / সি ++ এনাম, যা মার্শালিং সহজ করে তোলে।
আলেকজান্দ্রু নেদেলকু

50
আমি এটি ব্যবহার করে, প্রতিস্থাপন সংখ্যার সাথে object()
টুবু

9
মূল PEP354 আর নিছক প্রত্যাখ্যান করা হবে না, তবে এখন তাকে ছাড়িয়ে গেছে হিসাবে চিহ্নিত করা হয়েছে। পিইপি ৪৩৫ পাইথন ৩.৪-এর জন্য একটি স্ট্যান্ডার্ড এনাম যুক্ত করেছে। দেখুন python.org/dev/peps/pep-0435
পিটার হ্যানসেন

321

এখানে একটি বাস্তবায়ন:

class Enum(set):
    def __getattr__(self, name):
        if name in self:
            return name
        raise AttributeError

এটির ব্যবহার এখানে:

Animals = Enum(["DOG", "CAT", "HORSE"])

print(Animals.DOG)

51
চমৎকার। এটিকে ওভাররাইড করে আরও উন্নত করা যেতে পারে __setattr__(self, name, value)এবং __delattr__(self, name)যাতে আপনি দুর্ঘটনাক্রমে লিখে ফেলেন তবে Animals.DOG = CATএটি নিঃশব্দে সফল হবে না।
Joonas Pulakka

15
@ শাহজাপান: আকর্ষণীয়, তবে তুলনামূলকভাবে ধীর: প্রতিটি অ্যাক্সেসের মতো পরীক্ষা করা হয় Animals.DOG; এছাড়াও, কনস্ট্যান্টগুলির মানগুলি স্ট্রিং হয়, যাতে এই ধ্রুবকের সাথে তুলনাটি ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে ধীরে সেভ না হওয়া যায়।
এরিক ও লেবিগোট

3
@ শাহজাপান: আমি যুক্তি দিয়ে বলব যে এই সমাধানটি উদাহরণস্বরূপ আলেকজান্দ্রু বা মার্কের সংক্ষিপ্ত সমাধানগুলির মতো যথাযথ নয়। যদিও এটি একটি আকর্ষণীয় সমাধান। :)
এরিক হে লেবিগোট

আমি ওভারডিং পদ্ধতির পরিবর্তে setattr()ফাংশনটি ভিতরে ব্যবহার করার চেষ্টা করেছি । আমি ধরে নিচ্ছি এটি একইভাবে কাজ করা হচ্ছে: শ্রেণি এনুম (অবজেক্ট): ডিফ __init __ (স্ব, এনাম_স্ট্রিং_লিস্ট): যদি টাইপ (এনাম_স্ট্রিং_লিস্ট) == তালিকা: enum_string_list- এ enum_string এর জন্য: সেটেট্রটার (স্ব, এনাম_স্ট্রিং, এনাম_স্ট্রিং) অন্য: উত্থাপন অ্যাট্রিবিউটআরর__init__()__getattr__()
হার্শিথ জেভি

8
@ অ্যান্ড্রেটেরা: আপনি কীভাবে একটি try-exceptব্লকে সদস্যপদ নির্ধারণ করবেন ?
বিগুসাচ

209

আপনার যদি সংখ্যাসূচক মান প্রয়োজন হয় তবে এখানে দ্রুততম উপায়:

dog, cat, rabbit = range(3)

পাইথন ৩.x এ আপনি শেষে একটি তারকাযুক্ত স্থানধারকও যুক্ত করতে পারেন যা আপনার স্মৃতিশক্তি নষ্ট না করা এবং গণনা করতে না পারার ক্ষেত্রে পরিসরের বাকি সমস্ত মান সরিয়ে ফেলবে:

dog, cat, rabbit, horse, *_ = range(100)

1
তবে এতে আরও স্মৃতি লাগতে পারে!
এমজে

আমি অভিনীত স্থানধারকটির বিন্দুটি দেখতে পাচ্ছি না যে পাইথন আনপ্যাক করার মানগুলি পরীক্ষা করবে (তাই এটি আপনার জন্য গণনা করবে)।
গ্যাব্রিয়েল ডেভিলার্স

@ গ্যাব্রিয়েল ডেভিলারস, আমি মনে করি যে টিপলে নির্ধারিত সংখ্যক উপাদানগুলির মধ্যে কোনও মিল নেই তবে পাইথন একটি ব্যতিক্রম উত্থাপন করবে।
মার্ক হ্যারিসন

1
প্রকৃতপক্ষে, এটি আমার পরীক্ষায় রয়েছে (পাইথন 2,3) তবে এর অর্থ হ'ল প্রোগ্রামারের কোনও গণনা ভুল প্রথম পরীক্ষায় ধরা পড়বে (একটি বার্তা দিয়ে সঠিক গণনা দিয়ে)।
গ্যাব্রিয়েল ডেভিলার্স

1
আমি গণনা করতে পারি না। তারকাযুক্ত স্থানধারকটি কি আমার অর্থ সংস্থান করতে পারে?
জাভাদবা

130

আপনার নকল থেকে আপনার যা প্রয়োজন তা নির্ভর করবে আপনার জন্য সর্বোত্তম সমাধান enum

সাধারণ এনাম:

আপনার যদি enumকেবল আলাদা আইটেম সনাক্তকারী নামের তালিকা হিসাবে প্রয়োজন হয় তবে মার্ক হ্যারিসনের (উপরে) সমাধানটি দুর্দান্ত:

Pen, Pencil, Eraser = range(0, 3)

একটি ব্যবহার করে rangeআপনাকে যে কোনও প্রারম্ভিক মান সেট করতে দেয় :

Pen, Pencil, Eraser = range(9, 12)

উপরের পাশাপাশি, আপনার যদি প্রয়োজন হয় যে আইটেমগুলি কোনও ধরণের ধারকের অন্তর্ভুক্ত , তবে সেগুলি একটি শ্রেণিতে এম্বেড করুন:

class Stationery:
    Pen, Pencil, Eraser = range(0, 3)

এনাম আইটেমটি ব্যবহার করার জন্য, আপনাকে এখন ধারকটির নাম এবং আইটেমের নামটি ব্যবহার করতে হবে:

stype = Stationery.Pen

কমপ্লেক্স এনাম:

এনামের দীর্ঘ তালিকা বা এনামের জটিল ব্যবহারগুলির জন্য, এই সমাধানগুলি পর্যাপ্ত হবে না। পাইথন কুকবুক থেকে প্রকাশিত পাইথনে সিমুলেটিং এনুমারেশনের জন্য উইল ওয়ারের রেসিপিটি আপনি দেখতে পান । এর একটি অনলাইন সংস্করণ এখানে উপলভ্য ।

অধিক তথ্য:

পিইপি 354: পাইথনের গণনাগুলির পাইথনে এনামের প্রস্তাবের আকর্ষণীয় বিবরণ রয়েছে এবং কেন এটি বাতিল করা হয়েছিল।


7
সঙ্গে rangeআপনাকে প্রথমে যুক্তি বাদ যাবে যদি এটা 0
ToonAlfrink

অন্য কোনও জাল এনাম যা কিছু উদ্দেশ্যে স্যুট হয় my_enum = dict(map(reversed, enumerate(str.split('Item0 Item1 Item2'))))। তারপরে my_enumলুক-আপ ব্যবহার করা যেতে পারে, যেমন, my_enum['Item0']একটি ক্রম হিসাবে সূচি হতে পারে। আপনি str.splitযদি কোনও ডুপ্লিকেট থাকে তবে কোনও ফাংশনটিতে ব্যতিক্রম ছুঁড়ে ফেলতে চাইবেন an
আনা নিম্বাস

নিস! পতাকাগুলির জন্য আপনি করতে পারেনFlag1, Flag2, Flag3 = [2**i for i in range(3)]
মজ্কেলেক্স

এটি সেরা উত্তর
ইউরি পজনিয়াক

78

জাভা প্রি-জেডিকে 5 তে যে টাইপসেফ এনাম প্যাটার্ন ব্যবহার করা হয়েছিল তার কয়েকটি সুবিধা রয়েছে। আলেকজান্দ্রুর জবাবের মতো, আপনি একটি শ্রেণি তৈরি করেন এবং শ্রেণি স্তরের ক্ষেত্রগুলি এনাম মানগুলি; তবে এনাম মানগুলি ছোট সংখ্যার চেয়ে শ্রেণীর উদাহরণ class এটির সুবিধাটি রয়েছে যে আপনার এনাম মানগুলি অজান্তে ছোট পূর্ণসংখ্যার সাথে সমান তুলনা করে না, আপনি কীভাবে মুদ্রণ করছেন তা নিয়ন্ত্রণ করতে পারেন, কার্যকর হলে স্বেচ্ছাচারী পদ্ধতিগুলি যুক্ত করুন এবং আইসনস্ট্যান্স ব্যবহার করে দৃser়তার সাথে মন্তব্য করুন:

class Animal:
   def __init__(self, name):
       self.name = name

   def __str__(self):
       return self.name

   def __repr__(self):
       return "<Animal: %s>" % self

Animal.DOG = Animal("dog")
Animal.CAT = Animal("cat")

>>> x = Animal.DOG
>>> x
<Animal: dog>
>>> x == 1
False

পাইথন-দেব-এর সাম্প্রতিক এক সূত্রে উল্লেখ করা হয়েছে যে বন্যের মধ্যে কয়েকটি এনম লাইব্রেরি রয়েছে:


16
আমি মনে করি এটি খুব খারাপ পদ্ধতির। অ্যানিমাল.ডোজি = এনিমেল ("কুকুর") অ্যানিমাল.ডোজি 2 = এনিমেল ("কুকুর") অ্যানিম্যাল দান করুন Dডওজি == অ্যানিমাল.ডোগ 2 ব্যর্থ ...
বিভ্রান্তি

11
@ কনফিউশন ব্যবহারকারী কনস্ট্রাক্টরকে কল করার কথা নয়, সত্য যে একজন কনস্ট্রাক্টর এমনকি রয়েছে একটি বাস্তবায়ন বিশদ এবং আপনার সাথে যোগাযোগ করতে হবে যে কে কখনও আপনার কোড ব্যবহার করছে যে নতুন অঙ্কের মান তৈরি করা কোনও অর্থহীন নয় এবং এই বিদ্যমান কোডটি কার্যকর হবে না "সঠিক কাজটি করো". অবশ্যই এটি আপনাকে Animal.from_name ("কুকুর") -> Animal.DOG প্রয়োগ করতে বাধা দেয় না।
অ্যারন মাইনপা

13
"যে সুবিধাটি আপনার এনাম মানগুলি অজান্তে ছোট সংখ্যার সাথে সমান তুলনা করে না" এতে কী লাভ? আপনার এনামকে পূর্ণসংখ্যার সাথে তুলনা করার ক্ষেত্রে কী ভুল? বিশেষত আপনি যদি এনামটি ডাটাবেসে সংরক্ষণ করেন তবে আপনি সাধারণত এটি পূর্ণসংখ্যার হিসাবে সংরক্ষণ করতে চান, তাই আপনাকে এটি কোনও সময়ে পূর্ণসংখ্যার সাথে তুলনা করতে হবে।
ইবিজ

3
@ আ্যারন মাইনপা সঠিক। এটি এখনও এটি একটি ভাঙ্গা এবং অতিরিক্ত জটিল উপায় way
অ্যারোনস্টার্লিং

4
@ অ্যারোনএমসি স্মূথ এটি নির্ভর করে যে আপনি "এনামগুলি কেবল কয়েকটি অন্তর্নিহিতের নাম" বা আরও বেশি অবজেক্ট ভিত্তিক দৃষ্টিভঙ্গি যেখানে এনাম মানগুলি আসল বস্তু এবং পদ্ধতি রয়েছে (যা জাভাতে এনামগুলি কীভাবে ব্যবহার করে) এর উপর নির্ভর করে depends 1.5 টি, এবং যা নিরাপদ এনাম প্যাটার্নটি প্রকারের জন্য যাচ্ছিল)। ব্যক্তিগতভাবে, আমি স্যুইচ স্টেটমেন্ট পছন্দ করি না তাই আমি প্রকৃত বস্তুগুলির এনাম মানগুলির দিকে ঝুঁকছি।
অ্যারন মইনপাa

61

একটি এনাম ক্লাস ওয়ান-লাইনার হতে পারে।

class Enum(tuple): __getattr__ = tuple.index

এটি কীভাবে ব্যবহার করবেন (এগিয়ে এবং বিপরীত চেহারা, কী, মান, আইটেম ইত্যাদি)

>>> State = Enum(['Unclaimed', 'Claimed'])
>>> State.Claimed
1
>>> State[1]
'Claimed'
>>> State
('Unclaimed', 'Claimed')
>>> range(len(State))
[0, 1]
>>> [(k, State[k]) for k in range(len(State))]
[(0, 'Unclaimed'), (1, 'Claimed')]
>>> [(k, getattr(State, k)) for k in State]
[('Unclaimed', 0), ('Claimed', 1)]

আমি মনে করি এটি সবচেয়ে সহজ সমাধান সবচেয়ে মার্জিত সমাধান। পাইথন ২.৪-এ (হ্যাঁ, পুরাতন উত্তরাধিকারের সার্ভার) টিপলগুলি সূচী নেই। আমি তালিকা সহ প্রতিস্থাপন সমাধান।
ম্যাসিমো

আমি এটি একটি বৃহত্তর নোটবুকে চেষ্টা করেছি এবং আবিষ্কার করেছি যে এটি কোনও এক-লাইন সংজ্ঞা হিসাবে কাজ করবে না, তবে গেটআটার সংজ্ঞাটি দ্বিতীয় (ইন্ডেন্টেড) লাইনে রাখলে তা গ্রহণযোগ্য হবে।
ব্যবহারকারী5920660

এই সমাধানটি আমাকে inপরিচ্ছন্ন সদস্যদের সন্ধানের জন্য কীওয়ার্ডটি ব্যবহার করতে দিন । ব্যবহারের উদাহরণ:'Claimed' in Enum(['Unclaimed', 'Claimed'])
ফরজাদ আবদুলহোসেনি

51

সুতরাং, আমি একমত। আসুন পাইথনে প্রকারের সুরক্ষা প্রয়োগ করি না, তবে আমি নিজেকে নির্লজ্জ ভুল থেকে রক্ষা করতে চাই। সুতরাং আমরা এই সম্পর্কে কি মনে করি?

class Animal(object):
    values = ['Horse','Dog','Cat']

    class __metaclass__(type):
        def __getattr__(self, name):
            return self.values.index(name)

এটি আমার এনামগুলিকে সংজ্ঞায়িত করতে মান-সংঘাত থেকে রক্ষা করে।

>>> Animal.Cat
2

এর আরও একটি সুবিধাজনক সুবিধা রয়েছে: সত্যই দ্রুত বিপরীত লুকআপস:

def name_of(self, i):
    return self.values[i]

আমি এটি পছন্দ করি তবে আপনি টিউপলের সাথে দক্ষতার জন্য মানগুলিও লক করতে পারেন? আমি এটা দিয়ে প্রায় অভিনয় এবং একটি সংস্করণ নিয়ে এসেছেন যে args থেকে সেট self.values Init । এটি ঘোষণা করতে পেরে ভাল লাগছে Animal = Enum('horse', 'dog', 'cat')। আমি স্ব.মূল্যগুলিতে নিখোঁজ আইটেমটি পাওয়ার ক্ষেত্রে গ্যাটারে ভ্যালুআরআরও ধরি - পরিবর্তে সরবরাহকৃত নামের স্ট্রিংয়ের সাথে একটি অ্যাট্রিবিউটরর বাড়ানো ভাল বলে মনে হয়। আমি পাইথন ২.7 এ সেই ক্ষেত্রের সীমিত জ্ঞানের উপর ভিত্তি করে কাজ করার জন্য মেটাকগ্লাস পেতে পারি না, তবে আমার কাস্টম এনুম ক্লাস সোজা উদাহরণ পদ্ধতিতে সূক্ষ্মভাবে কাজ করে।
Trojjer

49

পাইথনের বিল্ট-ইন সমতুল্য নেই enum, এবং অন্যান্য উত্তরের নিজস্ব প্রয়োগের জন্য ধারণা রয়েছে (আপনি পাইথন কুকবুকের শীর্ষ সংস্করণেও আগ্রহী হতে পারেন )।

যাইহোক, enumসিতে যখন একটি ডাকা হত, আমি সাধারণত সহজ স্ট্রিং ব্যবহার করে শেষ করি : যেভাবে অবজেক্টস / বৈশিষ্ট্যগুলি প্রয়োগ করা হয়, সে কারণে (সি) পাইথন যেভাবেই সংক্ষিপ্ত স্ট্রিংগুলির সাথে খুব দ্রুত কাজ করার জন্য অনুকূলিত হয়েছে, তাই সেখানে পূর্ণসংখ্যার ব্যবহারে আসলেই কোনও কার্যকারিতা উপকার হবে না। টাইপস / অবৈধ মানগুলির বিরুদ্ধে রক্ষা করতে আপনি নির্বাচিত জায়গায় চেক .োকাতে পারেন।

ANIMALS = ['cat', 'dog', 'python']

def take_for_a_walk(animal):
    assert animal in ANIMALS
    ...

(ক্লাস ব্যবহারের তুলনায় একটি অসুবিধা হ'ল আপনি স্বতঃপূরণের সুবিধা হারাবেন)


2
আমি এই সমাধান পছন্দ। আমি যেখানে সম্ভব সেখানে অন্তর্নির্মিত ধরণের ব্যবহার করতে চাই।
সেউন ওসোয়া 18

সেই সংস্করণটি সত্যিই শীর্ষে নেই।
এটিতে কেবল

1
আসলে, "সঠিক" সংস্করণটি মন্তব্যে রয়েছে এবং আরও জটিল - মূল সংস্করণটিতে একটি ছোটখাটো বাগ রয়েছে bu
কেসব্যাশ

38

2013-05-10-এ, গাইডো পিইপি 435 পাইথন 3.4 স্ট্যান্ডার্ড লাইব্রেরিতে স্বীকার করতে সম্মত হয়েছে । এর অর্থ হ'ল পাইথন শেষ পর্যন্ত গণনার পক্ষে সমর্থন তৈরি করেছে!

পাইথন 3.3, 3.2, 3.1, 2.7, 2.6, 2.5 এবং 2.4 এর জন্য একটি ব্যাকপোর্ট উপলব্ধ। এটি এনপি 34 হিসাবে পাইপিতে রয়েছে

ঘোষণা:

>>> from enum import Enum
>>> class Color(Enum):
...     red = 1
...     green = 2
...     blue = 3

উপস্থাপনা:

>>> print(Color.red)
Color.red
>>> print(repr(Color.red))
<Color.red: 1>

পুনরাবৃত্তির:

>>> for color in Color:
...   print(color)
...
Color.red
Color.green
Color.blue

প্রোগ্রাম্যাটিক অ্যাক্সেস:

>>> Color(1)
Color.red
>>> Color['blue']
Color.blue

আরও তথ্যের জন্য , প্রস্তাব দেখুন । অফিসিয়াল ডকুমেন্টেশন সম্ভবত শীঘ্রই অনুসরণ করা হবে।


33

আমি পাইথনে এনামগুলি সংজ্ঞায়িত করতে পছন্দ করি:

class Animal:
  class Dog: pass
  class Cat: pass

x = Animal.Dog

পূর্ণসংখ্যার ব্যবহারের চেয়ে এটি আরও বেশি বাগ-প্রুফ, যেহেতু আপনাকে পূর্ণসংখ্যাগুলি অনন্য বলে নিশ্চিত করার বিষয়ে চিন্তা করতে হবে না (উদাহরণস্বরূপ যদি আপনি কুকুর = 1 এবং বিড়াল = 1 বলেছেন যে আপনি বোকা হয়ে থাকবেন)।

এটি স্ট্রিংগুলি ব্যবহার করার চেয়ে বেশি বাগ-প্রুফ, যেহেতু আপনাকে টাইপস সম্পর্কে চিন্তা করতে হবে না (যেমন x == "ক্যাট" নিঃশব্দে ব্যর্থ হয়, তবে x == এনিমেল।ক্যাট একটি রানটাইম ব্যতিক্রম)।


31
def M_add_class_attribs(attribs):
    def foo(name, bases, dict_):
        for v, k in attribs:
            dict_[k] = v
        return type(name, bases, dict_)
    return foo

def enum(*names):
    class Foo(object):
        __metaclass__ = M_add_class_attribs(enumerate(names))
        def __setattr__(self, name, value):  # this makes it read-only
            raise NotImplementedError
    return Foo()

এটি এর মতো ব্যবহার করুন:

Animal = enum('DOG', 'CAT')
Animal.DOG # returns 0
Animal.CAT # returns 1
Animal.DOG = 2 # raises NotImplementedError

যদি আপনি কেবল অনন্য প্রতীক চান এবং মানগুলির যত্ন না রাখেন তবে এই লাইনটি প্রতিস্থাপন করুন:

__metaclass__ = M_add_class_attribs(enumerate(names))

এর সাথে:

__metaclass__ = M_add_class_attribs((object(), name) for name in names)

11
আপনি যদি পরিবর্তিত enum(names)হন তবে এটি পরিষ্কার হয়ে যাবে enum(*names)- তবে ফোন করার সময় আপনি অতিরিক্ত বন্ধনী ফেলে দিতে পারেন।
ক্রিস লুটজ

আমি এই পদ্ধতির পছন্দ। নাম হিসাবে একই স্ট্রিংটিতে অ্যাট্রিবিউট মানটি সেট করতে আমি প্রকৃতপক্ষে এটি পরিবর্তন করেছি, যা এনিমেল.ডগ == 'ডগ' রয়েছে এমন দুর্দান্ত সম্পত্তি রয়েছে, তাই তারা স্বয়ংক্রিয়ভাবে আপনার জন্য স্ট্রিংফাই করে। (ডিবাগ আউটপুট মুদ্রণের জন্য প্রচুর সহায়তা করে))
টেড মেল্কজারেক

22

হুম ... আমি মনে করি এনুমের নিকটতম জিনিসটি একটি অভিধান হবে, এটি এর মতো সংজ্ঞায়িত:

months = {
    'January': 1,
    'February': 2,
    ...
}

অথবা

months = dict(
    January=1,
    February=2,
    ...
)

তারপরে, আপনি এই ধ্রুবকগুলির জন্য প্রতীকী নামটি ব্যবহার করতে পারেন:

mymonth = months['January']

অন্যান্য বিকল্প রয়েছে, যেমন টিপলসের তালিকার তালিকা, বা টিপলসের একটি টিপল, তবে অভিধানটি হ'ল একমাত্র যা আপনাকে মানটি অ্যাক্সেস করার জন্য "সিম্বলিক" (ধ্রুব স্ট্রিং) উপায় সরবরাহ করে।

সম্পাদনা: আমিও আলেকজান্দ্রুর উত্তর পছন্দ করি!


কম্বো বাক্স আইটেম হিসাবে প্রদর্শিত হওয়ার জন্য আপনার স্ট্রিংয়ের মানগুলির যেমন আপনার প্রয়োজন যেমন এর মানগুলি অ্যাক্সেস করার প্রয়োজন হয় তবে আপনি খুব সহজেই অভিধানের উপর পুনরাবৃত্তি করতে পারেন। পরিবর্তে পরিবর্তনের পরিবর্তে একটি অভিধান ব্যবহার করুন।
লেমুয়েল এডান

22

আর একটি, খুব সাধারণ, পাইথনে এনাম প্রয়োগ, এটি ব্যবহার করে namedtuple:

from collections import namedtuple

def enum(*keys):
    return namedtuple('Enum', keys)(*keys)

MyEnum = enum('FOO', 'BAR', 'BAZ')

বা, বিকল্পভাবে,

# With sequential number values
def enum(*keys):
    return namedtuple('Enum', keys)(*range(len(keys)))

# From a dict / keyword args
def enum(**kwargs):
    return namedtuple('Enum', kwargs.keys())(*kwargs.values())

setএই সাবক্লাসের উপরে থাকা পদ্ধতির মতো , এটির অনুমতি দেয়:

'FOO' in MyEnum
other = MyEnum.FOO
assert other == MyEnum.FOO

তবে এতে আরও নমনীয়তা রয়েছে কারণ এতে বিভিন্ন কী এবং মান থাকতে পারে। এটি অনুমতি দেয়

MyEnum.FOO < MyEnum.BAR

আপনি যদি অনুক্রমের সংখ্যা মানগুলিতে পূরণ করে এমন সংস্করণটি ব্যবহার করেন তবে প্রত্যাশিত হিসাবে কাজ করা।


22

পাইথন ৩.৪ থেকে এনামগুলির জন্য সরকারী সমর্থন থাকবে। পাইথন ৩.৪ ডকুমেন্টেশন পৃষ্ঠায় আপনি ডকুমেন্টেশন এবং উদাহরণগুলি পেতে পারেন ।

শ্রেণি বাক্য গঠন ব্যবহার করে অঙ্কগুলি তৈরি করা হয়, যা তাদের পড়তে এবং লিখতে সহজ করে তোলে। একটি বিকল্প তৈরি পদ্ধতি ফাংশনাল এপিআইতে বর্ণিত হয়েছে। একটি গণনা সংজ্ঞায়িত করতে, সাবক্লাস এনুম নিম্নরূপ:

from enum import Enum
class Color(Enum):
     red = 1
     green = 2
     blue = 3

ব্যাক পোর্টিং এখন পাশাপাশি সমর্থিত। এই পথেই যেতে হবে।
srock

20

আমি যা ব্যবহার করি:

class Enum(object):
    def __init__(self, names, separator=None):
        self.names = names.split(separator)
        for value, name in enumerate(self.names):
            setattr(self, name.upper(), value)
    def tuples(self):
        return tuple(enumerate(self.names))

ব্যবহারবিধি:

>>> state = Enum('draft published retracted')
>>> state.DRAFT
0
>>> state.RETRACTED
2
>>> state.FOO
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
AttributeError: 'Enum' object has no attribute 'FOO'
>>> state.tuples()
((0, 'draft'), (1, 'published'), (2, 'retracted'))

সুতরাং এটি আপনাকে রাজ্যের মতো পূর্ণসংখ্যার ধ্রুবক দেয় P


17

ডেভিডজি dicts ব্যবহার করার পরামর্শ দেয়। আমি আরও একধাপ এগিয়ে গিয়ে সেটগুলি ব্যবহার করব:

months = set('January', 'February', ..., 'December')

এখন আপনি পরীক্ষা করতে পারেন যে কোনও মানটি সেটির মতো মানগুলির সাথে একটির সাথে মেলে কিনা:

if m in months:

ডিএফের মতো, যদিও আমি সাধারণত এনামগুলির জায়গায় স্ট্রিং ধ্রুবক ব্যবহার করি।


হ্যাঁ, আপনি উত্তরাধিকার সূত্রে প্রাপ্ত এবং getattr পদ্ধতি সরবরাহ করলে আরও ভাল !
শাহজপান

16

এটি আমি দেখেছি সেরা এটি: "পাইথনে ফার্স্ট ক্লাস এনামস"

http://code.activestate.com/recipes/413486/

এটি আপনাকে একটি ক্লাস দেয় এবং ক্লাসে সমস্ত এনাম থাকে। এনামগুলি একে অপরের সাথে তুলনা করা যেতে পারে, তবে এর কোনও নির্দিষ্ট মান নেই; আপনি এগুলি পূর্ণসংখ্যার মান হিসাবে ব্যবহার করতে পারবেন না। (আমি প্রথমে এটিকে প্রতিহত করেছি কারণ আমি সি এনামগুলিতে অভ্যস্ত, যা পূর্ণসংখ্যার মান। ।) প্রতিটি এনাম একটি অনন্য মান। আপনি এনামগুলি মুদ্রণ করতে পারেন, আপনি তাদের উপর পুনরাবৃত্তি করতে পারেন, আপনি পরীক্ষা করতে পারেন যে এনামের মান এনামের মধ্যে "ইন" থাকে। এটি বেশ সম্পূর্ণ এবং চতুর।

সম্পাদনা (সিএফআই): উপরের লিঙ্কটি পাইথন 3 সামঞ্জস্যপূর্ণ নয়। পাইথন 3-তে আমার enum.py বন্দরটি এখানে:

def cmp(a,b):
   if a < b: return -1
   if b < a: return 1
   return 0


def Enum(*names):
   ##assert names, "Empty enums are not supported" # <- Don't like empty enums? Uncomment!

   class EnumClass(object):
      __slots__ = names
      def __iter__(self):        return iter(constants)
      def __len__(self):         return len(constants)
      def __getitem__(self, i):  return constants[i]
      def __repr__(self):        return 'Enum' + str(names)
      def __str__(self):         return 'enum ' + str(constants)

   class EnumValue(object):
      __slots__ = ('__value')
      def __init__(self, value): self.__value = value
      Value = property(lambda self: self.__value)
      EnumType = property(lambda self: EnumType)
      def __hash__(self):        return hash(self.__value)
      def __cmp__(self, other):
         # C fans might want to remove the following assertion
         # to make all enums comparable by ordinal value {;))
         assert self.EnumType is other.EnumType, "Only values from the same enum are comparable"
         return cmp(self.__value, other.__value)
      def __lt__(self, other):   return self.__cmp__(other) < 0
      def __eq__(self, other):   return self.__cmp__(other) == 0
      def __invert__(self):      return constants[maximum - self.__value]
      def __nonzero__(self):     return bool(self.__value)
      def __repr__(self):        return str(names[self.__value])

   maximum = len(names) - 1
   constants = [None] * len(names)
   for i, each in enumerate(names):
      val = EnumValue(i)
      setattr(EnumClass, each, val)
      constants[i] = val
   constants = tuple(constants)
   EnumType = EnumClass()
   return EnumType


if __name__ == '__main__':
   print( '\n*** Enum Demo ***')
   print( '--- Days of week ---')
   Days = Enum('Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su')
   print( Days)
   print( Days.Mo)
   print( Days.Fr)
   print( Days.Mo < Days.Fr)
   print( list(Days))
   for each in Days:
      print( 'Day:', each)
   print( '--- Yes/No ---')
   Confirmation = Enum('No', 'Yes')
   answer = Confirmation.No
   print( 'Your answer is not', ~answer)

এই রেসিপিটি পিইপি ভিত্তিক হিসাবে ব্যবহৃত হয়েছিল, যা প্রত্যাখ্যান করা হয়েছিল। python.org/dev/peps/pep-0354 একটি এক্সটেনশন যা আমি পছন্দ করি: এনাম মানগুলির একটি সদস্য ভেরিয়েবল থাকা উচিত যা আপনাকে অভ্যন্তরীণ পূর্ণসংখ্যার মানটি পেতে দেয়। ভুল করে কোনও পূর্ণসংখ্যার জন্য একটি এনাম castালানো সম্ভব হবে না, সুতরাং .__int__()পদ্ধতিটি এনামের জন্য একটি ব্যতিক্রম বাড়াতে পারে; তবে মানটি বের করার একটি উপায় থাকা উচিত। ক্লাস সংজ্ঞা সময়ে নির্দিষ্ট পূর্ণসংখ্যার মানগুলি সেট করা সম্ভব হওয়া উচিত, সুতরাং আপনি statমডিউলটিতে ধ্রুবকগুলির মতো জিনিসগুলির জন্য একটি এনাম ব্যবহার করতে পারেন ।
স্টিভাহ

16

সহজবোধ্য রাখো:

class Enum(object): 
    def __init__(self, tupleList):
            self.tupleList = tupleList

    def __getattr__(self, name):
            return self.tupleList.index(name)

তারপর:

DIRECTION = Enum(('UP', 'DOWN', 'LEFT', 'RIGHT'))
DIRECTION.DOWN
1

13

বাইনারি ফাইল ফর্ম্যাটটি ডিকোড করার উদ্দেশ্যে আমার একটি এনুম ক্লাসের প্রয়োজন ছিল। আমি যে বৈশিষ্ট্যগুলি চেয়েছিলাম তা হ'ল সংক্ষিপ্ত এনাম সংজ্ঞা, ইন্টিজার মান বা স্ট্রিং দ্বারা reprএনামের অবাধে উদাহরণস্বরূপ তৈরির ক্ষমতা এবং একটি দরকারী উত্সাহ। আমি এখানে যা শেষ করেছি তা এখানে:

>>> class Enum(int):
...     def __new__(cls, value):
...         if isinstance(value, str):
...             return getattr(cls, value)
...         elif isinstance(value, int):
...             return cls.__index[value]
...     def __str__(self): return self.__name
...     def __repr__(self): return "%s.%s" % (type(self).__name__, self.__name)
...     class __metaclass__(type):
...         def __new__(mcls, name, bases, attrs):
...             attrs['__slots__'] = ['_Enum__name']
...             cls = type.__new__(mcls, name, bases, attrs)
...             cls._Enum__index = _index = {}
...             for base in reversed(bases):
...                 if hasattr(base, '_Enum__index'):
...                     _index.update(base._Enum__index)
...             # create all of the instances of the new class
...             for attr in attrs.keys():
...                 value = attrs[attr]
...                 if isinstance(value, int):
...                     evalue = int.__new__(cls, value)
...                     evalue._Enum__name = attr
...                     _index[value] = evalue
...                     setattr(cls, attr, evalue)
...             return cls
... 

এটি ব্যবহারের একটি ছদ্মরূপ উদাহরণ:

>>> class Citrus(Enum):
...     Lemon = 1
...     Lime = 2
... 
>>> Citrus.Lemon
Citrus.Lemon
>>> 
>>> Citrus(1)
Citrus.Lemon
>>> Citrus(5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 6, in __new__
KeyError: 5
>>> class Fruit(Citrus):
...     Apple = 3
...     Banana = 4
... 
>>> Fruit.Apple
Fruit.Apple
>>> Fruit.Lemon
Citrus.Lemon
>>> Fruit(1)
Citrus.Lemon
>>> Fruit(3)
Fruit.Apple
>>> "%d %s %r" % ((Fruit.Apple,)*3)
'3 Apple Fruit.Apple'
>>> Fruit(1) is Citrus.Lemon
True

মূল বৈশিষ্ট্য:

  • str(), int()এবং repr()সমস্তই যথাসম্ভব দরকারী কার্যকর আউটপুট উত্পাদন করে যথাক্রমে সুনামের নাম, তার পূর্ণসংখ্যা মান এবং একটি পাইথন এক্সপ্রেশন যা গণনার পিছনে মূল্যায়ন করে।
  • কনস্ট্রাক্টর দ্বারা ফেরত গণনা করা মানগুলি পূর্বনির্ধারিত মানগুলিতে সীমাবদ্ধ, কোনও দুর্ঘটনাজনিত এনুম মান নেই।
  • গণিত মানগুলি সিলেটলেট; তাদের সাথে কঠোরভাবে তুলনা করা যেতে পারেis

এনামগুলি সংজ্ঞায়িত করা সহজ করার জন্য আমি নিজের মেটাক্লাস সহ একটি সুপারক্লাস ব্যবহার করতে পছন্দ করি। এখানে যা অনুপস্থিত তা হ'ল একটি __ কনটেন্টস__ পদ্ধতি। আমি যাচাই করতে সক্ষম হতে চাই যে প্রদত্ত ভেরিয়েবলটি এনামের একটি অংশ mostly বেশিরভাগ কারণে যে আমি এনামগুলিকে একটি ফাংশন প্যারামিটারের অনুমোদিত মানগুলির জন্য চাই।
xorsyst

এটি আসলে আমি তৈরি করা একটিটির কিছুটা ছাঁটাই সংস্করণ (যা আপনি এখানে খুঁজে পেতে পারেন: enum_strict.py ) v যা একটি __instancecheck__পদ্ধতি নির্ধারণ করে । ক্লাসগুলি উদাহরণের সংগ্রহ নয়, তাই 1 in Fruitঅবাস্তব। তবে, লিঙ্কযুক্ত সংস্করণটি সমর্থন করে isinstance(1, Fruit)যা শ্রেণি এবং উদাহরণগুলির ধারণার ক্ষেত্রে আরও সঠিক হবে।
সিঙ্গেলাইজেশন ইলিমিনেশন

তবে ক্লাসগুলি ভুলে যাওয়া এবং এনামগুলির ক্ষেত্রে চিন্তাভাবনা করা, তাহলে তাদের সংগ্রহ হিসাবে ভাবা বুদ্ধিমান হয়ে যায়। উদাহরণস্বরূপ, আমার কাছে ফাইল খোলার মোডগুলির একটি এনাম থাকতে পারে (MODE.OPEN, MODE.WRITE, ইত্যাদি)। আমি আমার ফাংশনটির প্যারামিটারগুলি যাচাই করতে চাই: যদি মোডে মোড থাকে: আইসেন্ট্যান্স (মোড, মোড) এর
xorsyst

আমি খুব অনুরূপ কিছু রেখেছি, যা কেবল ইনটসের
নাম_

11

পাইথনের নতুন মানটি পিইপি 435 , সুতরাং একটি এনাম ক্লাস পাইথনের ভবিষ্যতের সংস্করণগুলিতে উপলভ্য হবে:

>>> from enum import Enum

তবে এখনই এটি ব্যবহার শুরু করার জন্য আপনি মূল লাইব্রেরি ইনস্টল করতে পারেন যা পিইপিকে অনুপ্রাণিত করে:

$ pip install flufl.enum

তারপরে আপনি এটির অনলাইন গাইড অনুযায়ী এটি ব্যবহার করতে পারেন :

>>> from flufl.enum import Enum
>>> class Colors(Enum):
...     red = 1
...     green = 2
...     blue = 3
>>> for color in Colors: print color
Colors.red
Colors.green
Colors.blue

10
def enum(*sequential, **named):
    enums = dict(zip(sequential, [object() for _ in range(len(sequential))]), **named)
    return type('Enum', (), enums)

যদি আপনি এটির নাম রাখেন তবে এটি আপনার সমস্যা, তবে মানগুলির পরিবর্তে অবজেক্ট তৈরি না করলে আপনাকে এটি করতে দেয়:

>>> DOG = enum('BARK', 'WALK', 'SIT')
>>> CAT = enum('MEOW', 'WALK', 'SIT')
>>> DOG.WALK == CAT.WALK
False

এখানে বসানো অন্যান্য বাস্তবায়নগুলি ব্যবহার করার সময় (আমার উদাহরণে নামকরণের উদাহরণগুলি ব্যবহার করার সময়ও) আপনাকে অবশ্যই নিশ্চিত হতে হবে যে আপনি কখনই আলাদা এনাম থেকে বস্তুর তুলনা করার চেষ্টা করবেন না। এখানে একটি সম্ভাব্য সমস্যা:

>>> DOG = enum('BARK'=1, 'WALK'=2, 'SIT'=3)
>>> CAT = enum('WALK'=1, 'SIT'=2)
>>> pet1_state = DOG.BARK
>>> pet2_state = CAT.WALK
>>> pet1_state == pet2_state
True

বাবা!


9

আমি আসলেই আলেক থমাসের সমাধান পছন্দ করি (http://stackoverflow.com/a/1695250):

def enum(**enums):
    '''simple constant "enums"'''
    return type('Enum', (object,), enums)

এটি মার্জিত এবং পরিষ্কার দেখায় তবে এটি কেবল একটি ফাংশন যা নির্দিষ্ট বৈশিষ্ট্য সহ শ্রেণি তৈরি করে।

ফাংশনে সামান্য পরিবর্তন করে আমরা এটি আরও কিছুটা 'শত্রুতা' অভিনয় করতে পারি:

দ্রষ্টব্য: আমি পাইগটকের নতুন স্টাইল 'এনামস' (Gtk.MessageType.WARNING এর মত) এর আচরণ পুনরুত্পাদন করার চেষ্টা করে নিম্নলিখিত উদাহরণগুলি তৈরি করেছি

def enum_base(t, **enums):
    '''enums with a base class'''
    T = type('Enum', (t,), {})
    for key,val in enums.items():
        setattr(T, key, T(val))

    return T

এটি একটি নির্দিষ্ট ধরণের উপর ভিত্তি করে একটি এনাম তৈরি করে। পূর্ববর্তী ফাংশনের মতো অ্যাট্রিবিউট অ্যাক্সেস দেওয়ার পাশাপাশি এটি এমন আচরণ করে যা আপনি কোনও এনুমের সাথে প্রকারের বিষয়ে প্রত্যাশা করবেন। এটি বেস শ্রেণীর উত্তরাধিকার সূত্রে প্রাপ্ত হয়।

উদাহরণস্বরূপ, পূর্ণসংখ্যা enums:

>>> Numbers = enum_base(int, ONE=1, TWO=2, THREE=3)
>>> Numbers.ONE
1
>>> x = Numbers.TWO
>>> 10 + x
12
>>> type(Numbers)
<type 'type'>
>>> type(Numbers.ONE)
<class 'Enum'>
>>> isinstance(x, Numbers)
True

এই পদ্ধতিটি দিয়ে করা যেতে পারে এমন আরও একটি আকর্ষণীয় জিনিস হ'ল বিল্ট-ইন পদ্ধতিগুলিকে ওভাররাইড করে নির্দিষ্ট আচরণটি অনুকূলিতকরণ:

def enum_repr(t, **enums):
    '''enums with a base class and repr() output'''
    class Enum(t):
        def __repr__(self):
            return '<enum {0} of type Enum({1})>'.format(self._name, t.__name__)

    for key,val in enums.items():
        i = Enum(val)
        i._name = key
        setattr(Enum, key, i)

    return Enum



>>> Numbers = enum_repr(int, ONE=1, TWO=2, THREE=3)
>>> repr(Numbers.ONE)
'<enum ONE of type Enum(int)>'
>>> str(Numbers.ONE)
'1'

এই "বেস" টাইপ ধারণাটি ঝরঝরে :)
MestreLion

হ্যাঁ, নোট করুন আপনি নতুন পাইথন ৩.৪ দিয়ে এটিও করতে পারেন এনাম
দেবদেব

7

পিপিআই-র এনাম প্যাকেজ এনামগুলির একটি দৃ implementation় বাস্তবায়ন সরবরাহ করে। পূর্বের উত্তরে পিইপি 354 উল্লেখ করা হয়েছে; এটি প্রত্যাখ্যান করা হয়েছিল কিন্তু প্রস্তাবটি বাস্তবায়িত হয়েছিল http://pypi.python.org/pypi/enum

ব্যবহার সহজ এবং মার্জিত:

>>> from enum import Enum
>>> Colors = Enum('red', 'blue', 'green')
>>> shirt_color = Colors.green
>>> shirt_color = Colors[2]
>>> shirt_color > Colors.red
True
>>> shirt_color.index
2
>>> str(shirt_color)
'green'

5

আলেকজান্দ্রুর এনামগুলিতে ক্লাস কনস্ট্যান্ট ব্যবহার করার পরামর্শটি বেশ কার্যকরভাবে কাজ করে।

আমি মানব-পঠনযোগ্য স্ট্রিং উপস্থাপনা দেখার জন্য ধ্রুবকগুলির প্রতিটি সেটের জন্য একটি অভিধানও যুক্ত করতে চাই।

এটি দুটি উদ্দেশ্যে কাজ করে: ক) এটি আপনার এনামকে প্রিন্ট করার জন্য একটি সহজ উপায় সরবরাহ করে এবং খ) অভিধানটি যুক্তিযুক্তভাবে ধ্রুবকগুলিকে দলবদ্ধ করে তোলে যাতে আপনি সদস্যতার জন্য পরীক্ষা করতে পারেন।

class Animal:    
  TYPE_DOG = 1
  TYPE_CAT = 2

  type2str = {
    TYPE_DOG: "dog",
    TYPE_CAT: "cat"
  }

  def __init__(self, type_):
    assert type_ in self.type2str.keys()
    self._type = type_

  def __repr__(self):
    return "<%s type=%s>" % (
        self.__class__.__name__, self.type2str[self._type].upper())

4

আমি মূল্যবান বলে মনে করি এমন কয়েকটি ভিন্ন বৈশিষ্ট্য সহ এমন একটি পদ্ধতির সাথে যোগাযোগ করুন:

  • অনুমতি দেয়> এবং <এনামে অর্ডারের উপর ভিত্তি করে তুলনা, লেজিকাল ক্রম নয়
  • নাম, সম্পত্তি বা সূচী দ্বারা আইটেমটি সম্বোধন করতে পারে: xa, x ['a'] বা x [0]
  • [:] বা [-1] এর মতো স্লাইসিং অপারেশনগুলিকে সমর্থন করে

এবং সবচেয়ে গুরুত্বপূর্ণভাবে বিভিন্ন প্রকারের এনামগুলির মধ্যে তুলনা রোধ করে !

Http://code.activestate.com/recines/413486-first-class-enums-in-python এ কাছাকাছি ভিত্তিক

এই পদ্ধতির মধ্যে কী আলাদা তা চিত্রিত করতে এখানে অনেকগুলি নথি অন্তর্ভুক্ত করা হয়েছে।

def enum(*names):
    """
SYNOPSIS
    Well-behaved enumerated type, easier than creating custom classes

DESCRIPTION
    Create a custom type that implements an enumeration.  Similar in concept
    to a C enum but with some additional capabilities and protections.  See
    http://code.activestate.com/recipes/413486-first-class-enums-in-python/.

PARAMETERS
    names       Ordered list of names.  The order in which names are given
                will be the sort order in the enum type.  Duplicate names
                are not allowed.  Unicode names are mapped to ASCII.

RETURNS
    Object of type enum, with the input names and the enumerated values.

EXAMPLES
    >>> letters = enum('a','e','i','o','u','b','c','y','z')
    >>> letters.a < letters.e
    True

    ## index by property
    >>> letters.a
    a

    ## index by position
    >>> letters[0]
    a

    ## index by name, helpful for bridging string inputs to enum
    >>> letters['a']
    a

    ## sorting by order in the enum() create, not character value
    >>> letters.u < letters.b
    True

    ## normal slicing operations available
    >>> letters[-1]
    z

    ## error since there are not 100 items in enum
    >>> letters[99]
    Traceback (most recent call last):
        ...
    IndexError: tuple index out of range

    ## error since name does not exist in enum
    >>> letters['ggg']
    Traceback (most recent call last):
        ...
    ValueError: tuple.index(x): x not in tuple

    ## enums must be named using valid Python identifiers
    >>> numbers = enum(1,2,3,4)
    Traceback (most recent call last):
        ...
    AssertionError: Enum values must be string or unicode

    >>> a = enum('-a','-b')
    Traceback (most recent call last):
        ...
    TypeError: Error when calling the metaclass bases
        __slots__ must be identifiers

    ## create another enum
    >>> tags = enum('a','b','c')
    >>> tags.a
    a
    >>> letters.a
    a

    ## can't compare values from different enums
    >>> letters.a == tags.a
    Traceback (most recent call last):
        ...
    AssertionError: Only values from the same enum are comparable

    >>> letters.a < tags.a
    Traceback (most recent call last):
        ...
    AssertionError: Only values from the same enum are comparable

    ## can't update enum after create
    >>> letters.a = 'x'
    Traceback (most recent call last):
        ...
    AttributeError: 'EnumClass' object attribute 'a' is read-only

    ## can't update enum after create
    >>> del letters.u
    Traceback (most recent call last):
        ...
    AttributeError: 'EnumClass' object attribute 'u' is read-only

    ## can't have non-unique enum values
    >>> x = enum('a','b','c','a')
    Traceback (most recent call last):
        ...
    AssertionError: Enums must not repeat values

    ## can't have zero enum values
    >>> x = enum()
    Traceback (most recent call last):
        ...
    AssertionError: Empty enums are not supported

    ## can't have enum values that look like special function names
    ## since these could collide and lead to non-obvious errors
    >>> x = enum('a','b','c','__cmp__')
    Traceback (most recent call last):
        ...
    AssertionError: Enum values beginning with __ are not supported

LIMITATIONS
    Enum values of unicode type are not preserved, mapped to ASCII instead.

    """
    ## must have at least one enum value
    assert names, 'Empty enums are not supported'
    ## enum values must be strings
    assert len([i for i in names if not isinstance(i, types.StringTypes) and not \
        isinstance(i, unicode)]) == 0, 'Enum values must be string or unicode'
    ## enum values must not collide with special function names
    assert len([i for i in names if i.startswith("__")]) == 0,\
        'Enum values beginning with __ are not supported'
    ## each enum value must be unique from all others
    assert names == uniquify(names), 'Enums must not repeat values'

    class EnumClass(object):
        """ See parent function for explanation """

        __slots__ = names

        def __iter__(self):
            return iter(constants)

        def __len__(self):
            return len(constants)

        def __getitem__(self, i):
            ## this makes xx['name'] possible
            if isinstance(i, types.StringTypes):
                i = names.index(i)
            ## handles the more normal xx[0]
            return constants[i]

        def __repr__(self):
            return 'enum' + str(names)

        def __str__(self):
            return 'enum ' + str(constants)

        def index(self, i):
            return names.index(i)

    class EnumValue(object):
        """ See parent function for explanation """

        __slots__ = ('__value')

        def __init__(self, value):
            self.__value = value

        value = property(lambda self: self.__value)

        enumtype = property(lambda self: enumtype)

        def __hash__(self):
            return hash(self.__value)

        def __cmp__(self, other):
            assert self.enumtype is other.enumtype, 'Only values from the same enum are comparable'
            return cmp(self.value, other.value)

        def __invert__(self):
            return constants[maximum - self.value]

        def __nonzero__(self):
            ## return bool(self.value)
            ## Original code led to bool(x[0])==False, not correct
            return True

        def __repr__(self):
            return str(names[self.value])

    maximum = len(names) - 1
    constants = [None] * len(names)
    for i, each in enumerate(names):
        val = EnumValue(i)
        setattr(EnumClass, each, val)
        constants[i] = val
    constants = tuple(constants)
    enumtype = EnumClass()
    return enumtype


3

এই সমাধানটি তালিকা হিসাবে সংজ্ঞায়িত গণনার জন্য ক্লাস পাওয়ার একটি সহজ উপায় (কোনও বিরক্তিকর পূর্ণসংখ্যার কার্যাদি নেই):

enumeration.py:

import new

def create(class_name, names):
    return new.classobj(
        class_name, (object,), dict((y, x) for x, y in enumerate(names))
    )

example.py:

import enumeration

Colors = enumeration.create('Colors', (
    'red',
    'orange',
    'yellow',
    'green',
    'blue',
    'violet',
))

2
এটি ক্লাস তৈরির জন্য সত্যই একটি পুরানো-কালিক উপায়। কেবল type(class_name, (object,), dict(...))পরিবর্তে ব্যবহার করবেন না কেন ?
টার্মিনাস

3

যদিও মূল এনাম প্রস্তাবনা, পিইপি 354 বছর কয়েক আগে প্রত্যাখ্যান করা হয়েছিল, তা আবার সামনে আসছে। কিছু ধরণের এনামের যোগসূত্রটি 3.2-এ যুক্ত করা হয়েছিল, তবে এটি আবার 3.3 এ ঠেলে যায় এবং পরে ভুলে যায়। এবং এখন পাইথন ৩.৪ অন্তর্ভুক্ত করার উদ্দেশ্যে একটি পিইপি 435 রয়েছে । পিইপি 435 এর রেফারেন্স বাস্তবায়ন হ'ল flufl.enum

এপ্রিল 2013 পর্যন্ত, একটি সাধারণ toকমত্য বলে মনে হচ্ছে যে 3.4-র মধ্যে স্ট্যান্ডার্ড লাইব্রেরিতে কিছু যুক্ত করা উচিত — যতক্ষণ না লোকেরা "" কিছু "কী হবে সে বিষয়ে একমত হতে পারে। এটাই শক্ত অংশ। এখানে এবং এখানে শুরু হওয়া থ্রেডগুলি এবং 2013 এর শুরুর মাসগুলিতে দেড় ডজন অন্যান্য থ্রেড দেখুন।

এদিকে, প্রতিবার এটি প্রকাশের সাথে সাথে পিআইপিআই, অ্যাক্টিভেট ইত্যাদি ইত্যাদিতে বেশ কয়েকটি নতুন ডিজাইন এবং বাস্তবায়ন উপস্থিত হয়, তাই আপনি যদি এফএলইউএফএল নকশা পছন্দ না করেন তবে পিপিপি অনুসন্ধান করুন


3

নিম্নলিখিত ব্যবহার.

TYPE = {'EAN13':   u'EAN-13',
        'CODE39':  u'Code 39',
        'CODE128': u'Code 128',
        'i25':     u'Interleaved 2 of 5',}

>>> TYPE.items()
[('EAN13', u'EAN-13'), ('i25', u'Interleaved 2 of 5'), ('CODE39', u'Code 39'), ('CODE128', u'Code 128')]
>>> TYPE.keys()
['EAN13', 'i25', 'CODE39', 'CODE128']
>>> TYPE.values()
[u'EAN-13', u'Interleaved 2 of 5', u'Code 39', u'Code 128']

আমি এটি জ্যাঙ্গো মডেল পছন্দগুলির জন্য ব্যবহার করেছি এবং এটি দেখতে খুব অজগর। এটি আসলে কোনও এনুম নয়, তবে এটি কাজটি করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.