1. 程式人生 > 實用技巧 >關於python中Enum的個人總結

關於python中Enum的個人總結

關於python中Enum的個人總結

  1. 初識

    1. 可以通過enum模組匯入
  2. 語法

    1. 初始化:

      • 可以通過enum_ = Enum('class_name', names,start = 1)來建立,其中names可以是字串,可以是列表/元組。內部定義為:
       def _create_(cls, class_name, names, *, module=None, qualname=None, type=None, start=1):
              """Convenience method to create a new Enum class.
      
              `names` can be:
      
              * A string containing member names, separated either with spaces or
                commas.  Values are incremented by 1 from `start`.
              * An iterable of member names.  Values are incremented by 1 from `start`.
              * An iterable of (member name, value) pairs.
              * A mapping of member name -> value pairs.
      
              """
              metacls = cls.__class__
              bases = (cls, ) if type is None else (type, cls)
              _, first_enum = cls._get_mixins_(bases)
              classdict = metacls.__prepare__(class_name, bases)
      
              # special processing needed for names?
              if isinstance(names, str):
                  names = names.replace(',', ' ').split()
              if isinstance(names, (tuple, list)) and names and isinstance(names[0], str):
                  original_names, names = names, []
                  last_values = []
                  for count, name in enumerate(original_names):
                      value = first_enum._generate_next_value_(name, start, count, last_values[:])
                      last_values.append(value)
                      names.append((name, value))
      
              # Here, names is either an iterable of (name, value) or a mapping.
              for item in names:
                  if isinstance(item, str):
                      member_name, member_value = item, names[item]
                  else:
                      member_name, member_value = item
                  classdict[member_name] = member_value
              enum_class = metacls.__new__(metacls, class_name, bases, classdict)
      
              # TODO: replace the frame hack if a blessed way to know the calling
              # module is ever developed
              if module is None:
                  try:
                      module = sys._getframe(2).f_globals['__name__']
                  except (AttributeError, ValueError, KeyError) as exc:
                      pass
              if module is None:
                  _make_class_unpicklable(enum_class)
              else:
                  enum_class.__module__ = module
              if qualname is not None:
                  enum_class.__qualname__ = qualname
      
              return enum_class
      
      

      通過這樣就可以初始化並返回一個列舉類。

      1. 關於Enum的元素的使用

        • 通過原始碼可知:可以通過:enum_(value).vlaue/name,或者sth = enum.name-->sth.name/value,至於為什麼,需要檢視原始碼:

        • class DynamicClassAttribute:
              """Route attribute access on a class to __getattr__.  
          
              This is a descriptor, used to define attributes that act differently when
              accessed through an instance and through a class.  Instance access remains
              normal, but access to an attribute through a class will be routed to the
              class's __getattr__ method; this is done by raising AttributeError.
          
              This allows one to have properties active on an instance, and have virtual
              attributes on the class with the same name (see Enum for an example).
          
              """
              def __init__(self, fget=None, fset=None, fdel=None, doc=None):
                  self.fget = fget
                  self.fset = fset
                  self.fdel = fdel
                  # next two lines make DynamicClassAttribute act the same as property
                  self.__doc__ = doc or fget.__doc__
                  self.overwrite_doc = doc is None
                  # support for abstract methods
                  self.__isabstractmethod__ = bool(getattr(fget, '__isabstractmethod__', False))
          
              def __get__(self, instance, ownerclass=None):
                  if instance is None:
                      if self.__isabstractmethod__:
                          return self
                      raise AttributeError()
                  elif self.fget is None:
                      raise AttributeError("unreadable attribute")
                  return self.fget(instance)
          
              def __set__(self, instance, value):
                  if self.fset is None:
                      raise AttributeError("can't set attribute")
                  self.fset(instance, value)
          
              def __delete__(self, instance):
                  if self.fdel is None:
                      raise AttributeError("can't delete attribute")
                  self.fdel(instance)
          
              def getter(self, fget):
                  fdoc = fget.__doc__ if self.overwrite_doc else None
                  result = type(self)(fget, self.fset, self.fdel, fdoc or self.__doc__)
                  result.overwrite_doc = self.overwrite_doc
                  return result
          
              def setter(self, fset):
                  result = type(self)(self.fget, fset, self.fdel, self.__doc__)
                  result.overwrite_doc = self.overwrite_doc
                  return result
          
              def deleter(self, fdel):
                  result = type(self)(self.fget, self.fset, fdel, self.__doc__)
                  result.overwrite_doc = self.overwrite_doc
                  return result
          

          需要先例項化才能使用。

  3. 結語

    最後,Enum不僅可以是一個好的列舉也可以拿來代替一些繁瑣的類、狀態、順序等東西。比如說:`life = Enum('life', 'born baby teenager adult older die')。

    當然,更多的祕密等著你們自己去挖掘。