# Flag, auto(), unique, verify()

## Flag

***

`Flag` 與 `Enum` 的用法大致相同，但它是 `Enum` 的 Subclass，且 Flag members 支援 bitwise operators `&` (AND)、`|` (OR)、`^` (XOR) 和 `~` (INVERT)； 這些結果值是 enumeration members。

{% hint style="success" %}
**`Enum` 適合 enumeration members 更加互斥的情況，即，它們不應該組合使用。**

**`Flag` 適合 enumeration members 想要組合的情況。 一個用例可以是管理一組使用者權限。**
{% endhint %}

{% code title="PYTHON" %}

```python
import enum

class Permission(enum.Flag):
    READ = enum.auto()
    WRITE = enum.auto()
    EXECUTE = enum.auto()
    W=enum.auto()

# Individual permissions
print(Permission.READ.value)     # Output: 1
print(Permission.WRITE.value)    # Output: 2
print(Permission.EXECUTE.value)  # Output: 4

# Combined permissions
read_write = Permission.READ | Permission.WRITE
print(read_write)                     # Output: Permission.READ|WRITE

# Checking if a certain permission is in the combination
print(Permission.READ in read_write)  # Output: True
print(type(read_write))               # <flag 'Permission'>
```

{% endcode %}

### IntFlag

***

`IntFlag` 與 `Flag` 的用法大致相同，但它是 `Flag` 的 Subclass ，且 enumeration 值是 `str` 的實例。

`IntFlag` 更進一步，使 enumeration members 的行為更像整數。`IntFlag` members ，可以參與所有 `int` 的 operations。如果對 `IntFlag` members 執行任何整數運算，則結果值將失去 enumeration 狀態。

`IntFlag` 和 `Enum` 之間的另一個重要區別是，如果沒有設置 Flag(值會為0)，則 `bool()` 評估為 `False`。

{% hint style="success" %}
**自定義 `IntFlag` members 時要小心，以避免意外地將組合定義為單個權限。或是直接使用 `auto` 定義 members。**&#x20;

例如：為 member 分配 `3` 的權限，將意味著它同時包含 `1` 和 `2` 的權限。
{% endhint %}

{% code title="PYTHON" %}

```python
import enum

class Permission(enum.IntFlag):
    NONE = 0
    READ = 1
    WRITE = 2
    EXECUTE = 4
    ALL = 7

# Individual permissions
print(Permission.READ)   # Output: 1

# Combined permissions
read_write = Permission.READ | Permission.WRITE
print(read_write)        # Output: 3
print(type(read_write))  # Output:  <flag 'Permission'> 

# Checking if a certain permission is in the combination
print(Permission.READ in read_write)  # Output: True

# Compare with integers
print(Permission.ALL == 7)  # Output: True

print(Permission.ALL & Permission.NONE)       # Output: 0
print(bool(Permission.ALL & Permission.NONE)) # Output: False
```

{% endcode %}

### Flag 命名組合

***

命名組合被視為別名。別名在 iteration 期間不會顯示，但可以使用值查找。 `IntFlag` members 也是 `int` 的 Subclass，所以可以與 int 組合。

{% code title="PYTHON" %}

```python
from enum import IntFlag

class Perm(IntFlag):
    R = 4
    W = 2
    X = 1

print(Perm.R | Perm.W)  # Output: 6
print(Perm.R + Perm.W)  # Output: 6

RW = Perm.R | Perm.W
print(Perm.R in RW)     # Output: True
```

{% endcode %}

### Flag boundary 參數

***

控制 `Flag` 及其 Subclasses 中如何處理超出範圍的值。

`KEEP`：超出範圍的值將被保留，並且 `Flag` membership 將被保留。這是 `IntFlag` 的預設值。 `EJECT`: 超出範圍的值將失去其 `Flag` membership ，並恢復為 `int`。 `CONFORM`: 超出範圍的值已將刪除無效值，留下有效的 `Flag` 值： `STRICT`: 超出範圍的值會導致引發 ValueError。這是 `Flag` 的預設值。

{% code title="PYTHON" %}

```python
import enum

class KeepFlag(enum.Flag, boundary=enum.KEEP):
    RED = enum.auto()
    GREEN = enum.auto()
    BLUE = enum.auto()


print(KeepFlag(2**2))        # Output: KeepFlag.BLUE
print(KeepFlag(2**2 + 2**4)) # Output: KeepFlag.BLUE|16

print(KeepFlag.RED.value)    # Output: 1
print(KeepFlag.GREEN.value)  # Output: 2
print(KeepFlag.BLUE.value)   # Output: 4

# =========================================================
class KeepFlag(enum.Flag, boundary=enum.EJECT):
    RED = enum.auto()
    GREEN = enum.auto()
    BLUE = enum.auto()
print(KeepFlag(2**2 + 2**4)) # Output: 20

# =========================================================
class KeepFlag(enum.Flag, boundary=enum.CONFORM):
    RED = enum.auto()
    GREEN = enum.auto()
    BLUE = enum.auto()
print(KeepFlag(2**2 + 2**4)) # Output: KeepFlag.BLUE

# =========================================================
class KeepFlag(enum.Flag, boundary=enum.STRICT):
    RED = enum.auto()
    GREEN = enum.auto()
    BLUE = enum.auto()
print(KeepFlag(2**2 + 2**4)) 
'''
Output: 
ValueError: <flag 'KeepFlag'> invalid value 20
    given 0b0 10100
  allowed 0b0 00111
'''
```

{% endcode %}

## auto()

***

`auto` 可以用來代替 Enum 的值，其值是 `auto` 的實例。 是一個為 Enum members 生成值的 Class。目的是簡化 enumerations 的創建，其中 members 的確切值並不重要，從而使開發人員能夠專注於程式碼中更有意義的部分。

使用 `auto` 時，將調用 Enum 的 `_generate_next_value_()` 來獲取適當的值。

* 對於 `Enum` 和 `IntEnum`，Enum 的值將是最後一個值加 1。
* 對於 `Flag` 和 `IntFlag` ，Enum 的值將是第一個大於最高值的 2 的冪 (次方)。
* 對於 `StrEnum` ，Enum 的值將是 member’s name 的小寫版本。

如果將 `auto()` 與手動指定的 Enum 值混合使用時，必須小心。

{% hint style="success" %}
**Python 3.11.1 更新。**&#x20;

**3.11.1 之前**: `auto()` 必須是賦值右側的唯一項。&#x20;

**3.11.1 開始**：您可以以更靈活的方式使用 `auto()` ，可以同一行上的其他表達式或值組合起來。這允許更複雜的 enum 定義。
{% endhint %}

{% code title="PYTHON" %}

```python
from enum import Enum, auto

# After Python 3.11.1
class Color(Enum):
    RED = auto() 
    GREEN = auto(), -2
    YELLOW = (auto(), -3)
    BLUE = [auto(), -3]   # ❌❌
    
print(Color.RED.value)    # Output: 1
print(Color.GREEN.value)  # Output: (2, -2)
print(Color.YELLOW.value) # Output: (3, -3)
print(Color.BLUE.value)   # Output: [auto(_auto_null), -3]

# =========================================================
# Before Python 3.11.1
class Color(Enum):
    RED = auto() 
    GREEN = auto(), -2    # ❌❌
    YELLOW = (auto(), -3) # ❌❌
    BLUE = [auto(), -3]   # ❌❌

print(Color.RED.value)    # Output: 1
print(Color.GREEN.value)  # Output: (<enum.auto object at 0x0000015851FCBFD0>, -2)
print(Color.YELLOW.value) # Output: (<enum.auto object at 0x0000015851FCBF40>, -3)
print(Color.BLUE.value)   # Output: [<enum.auto object at 0x0000015851FCBF10>, -3]
```

{% endcode %}

### 範例 – auto()

***

{% code title="PYTHON" %}

```python
from enum import Enum, auto

# Enumeration has eight members 
# Representing the eight planets of the Solar System. 
class Planet(Enum):
    MERCURY = auto()
    VENUS = auto()
    EARTH = auto()
    MARS = auto()
    JUPITER = auto()
    SATURN = auto()
    URANUS = auto()
    NEPTUNE = auto()

    def describe(self):
        if self == Planet.EARTH:
            return "Home, sweet home!"
        else:
            return "This is planet " + self.name

print(Planet.EARTH.describe())  # Output: Home, sweet home!
print(Planet.MARS.describe())   # Output: This is planet MARS
print(Planet.EARTH.value < Planet.MARS.value) # Output: True
```

{% endcode %}

### \_\_generate\_next\_value\_\_

***

您可以重寫 enumeration classes 中的 `_generate_next_value_` 方法來更改 `auto()` 為 members 賦值的方式。 當您想要使用 `auto()` ，但需要對分配的值進行更多控制時，這非常有用。

{% code title="PYTHON" %}

```python
_generate_next_value_(name, start, count, last_values)
```

{% endcode %}

<table><thead><tr><th width="188">參數</th><th>說明</th></tr></thead><tbody><tr><td><strong>name</strong></td><td>正在定義的 member's name。</td></tr><tr><td><strong>start</strong></td><td>Enum 起始值。</td></tr><tr><td><strong>count</strong></td><td>當前已經定義的 members 數量。</td></tr><tr><td><strong>last_values</strong></td><td>以前值的 List。</td></tr></tbody></table>

{% code title="PYTHON" %}

```python
from enum import Enum, auto

class PowersOfThree(Enum):
    @staticmethod  # 需求 python 3.10 以上
    def _generate_next_value_(name, start, count, last_values):
        return 3 * (count + 1)

    FIRST = auto()
    SECOND = auto()
    THIRD = auto()

print(PowersOfThree.FIRST.value)  # Output: 3
print(PowersOfThree.SECOND.value) # Output: 6
print(PowersOfThree.THIRD.value)  # Output: 9
```

{% endcode %}

{% code title="PYTHON" %}

```python
import enum

class AutoName(enum.Enum):
    def _generate_next_value_(name, start, count, last_values):
        return name

class Ordinal(AutoName):
    NORTH = enum.auto()
    SOUTH = enum.auto()
    EAST = enum.auto()
    WEST = enum.auto()

print(list(Ordinal))
# Output:
# [<Ordinal.NORTH: 'NORTH'>, <Ordinal.SOUTH: 'SOUTH'>, <Ordinal.EAST: 'EAST'>, <Ordinal.WEST: 'WEST'>]
```

{% endcode %}

## object()

***

`object()` 是 Python 中的一個 built-in 函數，它返回一個新的無特徵物件。 `object` 是所有 Class 的基礎，它包含所有 Class 預設的 built-in 屬性和方法。

當您希望每個 enum member 都具有真正唯一且明確的值時，這可能很有用。例如：避免某些類型的錯誤，尤其是在具有許多 enum 類型的大型程序中。

然而，使用 `object()` 實例作為 enum 值也有一些缺點。 例如：這些值不是人類可讀的，並且無法序列化為 JSON 或其他格式。 它還可能使 debugging 變得更加困難，因為這些值不提供有關它們所代表的內容的任何訊息。 因此，請謹慎使用此功能，並考慮您的具體情況是否利大於弊。

在此範例中，`Unique` enum 具有三個 members，每個 member 的值都是唯一的 `object()` 實例。 當你運行這個程序時，

{% code title="PYTHON" %}

```python
from enum import Enum

class Unique(Enum):
    FIRST = object()
    SECOND = object()
    THIRD = object()

print(Unique.FIRST.value)   # Output: <object object at 0x000002CE0C8D4260>
print(Unique.SECOND.value)  # Output: <object object at 0x000002CE0C8D4260>
print(Unique.THIRD.value)   # Output: <object object at 0x000002CE0C8D4270>
print(Unique.FIRST.value == Unique.SECOND.value) # Output: False
```

{% endcode %}

{% hint style="info" %}
**確切的輸出會有所不同，因為 `object()` 實例會被輸出為 `<object at 0x...>`，其中`...`是物件的 memory 地址。**
{% endhint %}

## @unique, @verify()

***

`@unique` 確保 enum class 中的所有 enumeration 值都是唯一的 (獨立的)； 如果有任何重複，它將引發 ValueError 。

{% code title="PYTHON" %}

```python
import enum

@enum.unique
class Color(enum.Enum):
    RED = 1
    GREEN = 2
    BLUE = 2

    def describe(self):
        # this is a member function
        return f"This is a color with value {self.value}"

    @classmethod
    def favorite_color(cls):
        return cls.GREEN

# Usage:
print(Color.RED)               # Output: Color.RED
print(Color.RED.value)         # Output: 1
print(Color.RED.describe())    # Output: This is a color with value 1
print(Color.favorite_color())  # Output: Color.GREEN

'''
Output: 
ValueError: duplicate values found in <enum 'Color'>: BLUE -> GREEN
'''
```

{% endcode %}

`verify()` decorator 用於確保各種限制條件； 失敗的限制條件會導致 ValueError。

`UNIQUE`: 確保每個值只有唯一的 enum member。 `CONTINUOUS`: 確保最低值的 member 和最高值的 member 之間不存在缺失值。 `NAMED_FLAGS`: 確保任何 flag 包含已經命名的 flags。當 flag 的值由 `auto()` 生成時，忽略檢查該 flag。

{% hint style="info" %}
**`CONTINUOUS`，`NAMED_FLAGS` 僅支援整數的值。**
{% endhint %}

{% code title="PYTHON" %}

```python
import enum

@enum.verify(enum.UNIQUE)
class Color(enum.Enum):
    RED = 1
    GREEN = 2
    BLUE = 3
    CRIMSON = 1
# Output:
# ValueError: aliases found in <enum 'Color'>: CRIMSON -> RED

@enum.verify(enum.CONTINUOUS)
class Color(enum.Enum):
    RED = 1
    GREEN = 2
    BLUE = 5
# Output:
# ValueError: invalid enum 'Color': missing values 3, 4

@enum.verify(enum.NAMED_FLAGS)
class Color(enum.Flag):
    RED = 1
    GREEN = 2
    BLUE = 4
    WHITE = 15
    NEON = 31

# ValueError: invalid Flag 'Color': aliases WHITE and NEON are missing combined values of 0x18 
# [use enum.show_flag_values(value) for details]

print(enum.show_flag_values(15)) # Output: [1, 2, 4, 8]
print(enum.show_flag_values(31)) # Output: [1, 2, 4, 8, 16]

```

{% endcode %}

## show\_flag\_values()

***

`show_flag_values(value)` 返回 flag 值中包含的所有二次冪整數的列表。

{% code title="PYTHON" %}

```python
import enum

class Color(enum.Flag):
    RED = 1
    GREEN = 2
    BLUE = 4
    WHITE = 15
    NEON = 31

print(enum.show_flag_values(15)) # Output: [1, 2, 4, 8]
print(enum.show_flag_values(31)) # Output: [1, 2, 4, 8, 16]
```

{% endcode %}

## \_\_init\_\_

***

`__init__()` 用於在創建 Class 的實例後對其進行初始化。 在 `Enum` 的 context 中，`__init__()` 方法可用於為 enum 的每個 member 執行附加設置。

**範例 1**：為 enum members 分配附加屬性，每個 member 都有一個名稱和一個縮寫。

{% code title="PYTHON" %}

```python
from enum import Enum

class State(Enum):
    Alabama = ('AL', 'Montgomery')
    Alaska = ('AK', 'Juneau')

    def __init__(self, abbreviation, capital):
        self.abbreviation = abbreviation
        self.capital = capital

print(State.Alabama)              # Output: State.Alabama
print(State.Alabama.abbreviation) # Output: 'AL'
print(State.Alabama.capital)      # Output: 'Montgomery'
```

{% endcode %}

重寫 `__init__()` 來為 enum 的每個 member 提供額外的設置。`__init__()` 不返回任何內容； 相反，它直接修改實例。 如果您嘗試從 `__init__()` 返回除 `None` 之外的任何內容，您將得到一個 `TypeError`。

`__init__()` 的參數必須與定義 enum members 時提供的值匹配。 在 `State` Class 中，每個 enum member 都使用兩個 Tuple Strings 定義，這兩個 Strings 與 `__init__()` 的`abbreviation` 和 `capital` 參數匹配。

{% hint style="info" %}
請注意，在定義 enum member 後對其進行修改，通常被認為是不好的做法，因為 enums 是 immutable (不可變的)。
{% endhint %}

### 範例 – \_\_init\_\_

***

Enum member 的值存儲在 `.value` 屬性中，但可以使用 `__init__()` 向 enum members 加入其他屬性。 這些附加屬性的訪問方式就像 Python 物件的任何其他屬性一樣。

{% code title="PYTHON" %}

```python
from enum import Enum

class Month(Enum):
    January = 1
    February = 2
    March = 3
    # ...

    def __init__(self, index):
        self.index = index
        self.days = self.compute_days()

    def compute_days(self):
        if self.index in (1, 3):
            return 31
        elif self.index == 2:
            return 28
        else:
            return 30

print(Month.January.value)  # Output: 1
print(Month.January.index)  # Output: 1
print(Month.January.days)   # Output: 31

print(Month.February.value) # Output: 2
print(Month.February.index) # Output: 2
print(Month.February.days)  # Output: 28
```

{% endcode %}

{% code title="PYTHON" %}

```python
from enum import Enum

class Planet(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__(self, mass, radius):
        self.mass = mass       # in kilograms
        self.radius = radius   # in meters

    @property
    def surface_gravity(self):
        # universal gravitational constant  (m3 kg-1 s-2)
        G = 6.67300E-11
        return G * self.mass / (self.radius * self.radius)

print(Planet.EARTH.value)   # Output: (5.976e+24, 6378140.0)
print(Planet.EARTH.mass)    # Output: 5.976e+24
print(Planet.EARTH.radius)  # Output: 6378140.0
print(Planet.EARTH.surface_gravity)  # Output: 9.802652743337129
```

{% endcode %}

## Functional API

***

`Enum` 函數 API 允許您創建 enumeration 類型，這些類型基本上是一組值的符號名稱。

{% code title="PYTHON" %}

```python
Enum(
    value='NewEnumName',
    names=<...>, *,
    module='...',
    qualname='...',
    type=<mixed-in class>,
    start=1)
```

{% endcode %}

<table><thead><tr><th width="170">參數</th><th>說明</th></tr></thead><tbody><tr><td><strong>value</strong></td><td>新 enumeration 的名稱。</td></tr><tr><td><strong>names</strong></td><td>enum members。這可以是 String、mapping、 names iterator 或 (name, value) pairs iterator。 這也可以是空格或逗號分隔的 String（除非另有說明，值將從 1 開始）</td></tr><tr><td><strong>module</strong></td><td>用作 enum 的 <code>__module__</code> 屬性。對於 pickling 和 introspection 很有用。</td></tr><tr><td><strong>qualname</strong></td><td>用作 enum 的 <code>__qualname__</code> 屬性。對於 introspection 很有用。</td></tr><tr><td><strong>type</strong></td><td>用作 Mixed-in Class。即，它定義 enumeration 的特定行為。 如果您希望 enum members 表現得像整數、Strings 等，這會很有用。</td></tr><tr><td><strong>start</strong></td><td>定義 enum members 自動編號的起始編號。</td></tr></tbody></table>

{% hint style="info" %}
**`Enum` 函數式 API 靈活且用途廣泛，使您能夠創建具有不同行為的複雜 enumeration 類型。**
{% endhint %}

{% hint style="warning" %}
**如果未提供 `module`，並且 Enum 無法確定它是什麼，則新的 Enum members 將不會 unpicklable； 為了使錯誤更接近 source，pickling 將被禁用。**
{% endhint %}

{% code title="PYTHON" %}

```python
from enum import Enum, StrEnum

Color = Enum("Color", 'RED GREEN BLUE')
Color = Enum("Color", 'RED,GREEN,BLUE')
Color = Enum("Color", 'RED, GREEN, BLUE')
Color = Enum("Color", ['RED', 'GREEN', 'BLUE'])
Color = Enum("Color", [('RED', 1), ('GREEN', 2), ('BLUE', 3)])
Color = Enum("Color", {"RED": 1, 'GREEN': 2, 'BLUE': 3})
print(list(Color))  # Output: [<Color.RED: 1>, <Color.GREEN: 2>, <Color.BLUE: 3>]


Fruit = Enum("Fruit", ["APPLE", "BANANA", "CHERRY"], start=10)
print(list(Fruit))  # Output: [<Fruit.APPLE: 10>, <Fruit.BANANA: 11>, <Fruit.CHERRY: 12>]

Color = Enum("Color", {"RED": "#FF0000", 
                       "GREEN": "#008000", 
                       "BLUE": "#0000FF"})
print(list(Color))  # Output: [<Color.RED: '#FF0000'>, 
                              #<Color.GREEN: '#008000'>, 
                              #<Color.BLUE: '#0000FF'>]

# Using mixed-in type
class CustomEnum(StrEnum):
    pass

Direction = Enum("Direction", "NORTH EAST SOUTH WEST", type=CustomEnum)
print(list(CustomEnum))  # Output: []
print(list(Direction))   # Output: [<Direction.NORTH: '1'>, <Direction.EAST: '2'>, 
                                  # <Direction.SOUTH: '3'>, <Direction.WEST: '4'>]
```

{% endcode %}

{% code title="PYTHON" %}

```python
from enum import Enum

# Creating an Enum using functional API
Fruit = Enum(
    value="Fruit",
    names=["APPLE", "BANANA", "CHERRY"],
    module='main',
    qualname='main.Fruit',)

print(Fruit.__module__)    # Outputs: main
print(Fruit.__qualname__)  # Outputs: main.Fruit
```

{% endcode %}

\ <br>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.xiwind-corp.com/tech/python-library/enum-lie-ju-class/flag-auto-unique-verify.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
