Hub Python Library documentation

Strict Dataclasses

Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Strict Dataclasses

Gói huggingface_hub cung cấp tiện ích để tạo strict dataclasses. Đây là các phiên bản nâng cao của dataclass chuẩn của Python với các tính năng xác thực bổ sung. Strict dataclasses đảm bảo rằng các trường được xác thực cả trong quá trình khởi tạo và gán giá trị, khiến chúng trở nên lý tưởng cho các kịch bản mà tính toàn vẹn của dữ liệu là yếu tố then chốt.

Tổng quan

Strict dataclasses được tạo bằng decorator @strict. Chúng mở rộng chức năng của các dataclass thông thường bằng cách:

  • Xác thực kiểu trường dựa trên gợi ý kiểu
  • Hỗ trợ trình xác thực tùy chỉnh cho các kiểm tra bổ sung
  • Tùy chọn cho phép các đối số từ khóa tùy ý trong bộ khởi tạo
  • Xác thực các trường cả khi khởi tạo và trong quá trình gán

Lợi ích

  • Tính toàn vẹn dữ liệu: Đảm bảo các trường luôn chứa dữ liệu hợp lệ
  • Dễ sử dụng: Tích hợp liền mạch với module dataclass của Python
  • Tính linh hoạt: Hỗ trợ các trình xác thực tùy chỉnh cho logic xác thực phức tạp
  • Nhẹ: Không yêu cầu các phụ thuộc bổ sung như Pydantic, attrs hoặc các thư viện tương tự

Cách sử dụng

Ví dụ cơ bản

from dataclasses import dataclass
from huggingface_hub.dataclasses import strict, as_validated_field

# Custom validator to ensure a value is positive
@as_validated_field
def positive_int(value: int):
    if not value > 0:
        raise ValueError(f"Value must be positive, got {value}")

@strict
@dataclass
class Config:
    model_type: str
    hidden_size: int = positive_int(default=16)
    vocab_size: int = 32  # Default value

    # Methods named `validate_xxx` are treated as class-wise validators
    def validate_big_enough_vocab(self):
        if self.vocab_size < self.hidden_size:
            raise ValueError(f"vocab_size ({self.vocab_size}) must be greater than hidden_size ({self.hidden_size})")

Các trường được xác thực trong quá trình khởi tạo:

config = Config(model_type="bert", hidden_size=24)   # Valid
config = Config(model_type="bert", hidden_size=-1)   # Raises StrictDataclassFieldValidationError

Sự nhất quán giữa các trường cũng được xác thực trong quá trình khởi tạo (xác thực theo lớp):

# `vocab_size` too small compared to `hidden_size`
config = Config(model_type="bert", hidden_size=32, vocab_size=16)   # Raises StrictDataclassClassValidationError

Các trường cũng được xác thực trong quá trình gán:

config.hidden_size = 512  # Valid
config.hidden_size = -1   # Raises StrictDataclassFieldValidationError

Để chạy lại xác thực cho toàn bộ lớp sau khi gán, bạn phải gọi .validate một cách tường minh:

config.validate()  # Runs all class validators

Trình xác thực tùy chỉnh

Bạn có thể gắn nhiều bộ xác thực tùy chỉnh vào các trường bằng cách sử dụng validated_field. Một bộ xác thực là một hàm có thể gọi nhận một đối số duy nhất và ném ngoại lệ nếu giá trị không hợp lệ.

from dataclasses import dataclass
from huggingface_hub.dataclasses import strict, validated_field

def multiple_of_64(value: int):
    if value % 64 != 0:
        raise ValueError(f"Value must be a multiple of 64, got {value}")

@strict
@dataclass
class Config:
    hidden_size: int = validated_field(validator=[positive_int, multiple_of_64])

Trong ví dụ này, cả hai bộ xác thực đều được áp dụng cho trường hidden_size.

Các đối số từ khóa bổ sung

Mặc định, strict dataclasses chỉ chấp nhận các trường được định nghĩa trong lớp. Bạn có thể cho phép các đối số từ khóa bổ sung bằng cách đặt accept_kwargs=True trong bộ trang trí @strict.

from dataclasses import dataclass
from huggingface_hub.dataclasses import strict

@strict(accept_kwargs=True)
@dataclass
class ConfigWithKwargs:
    model_type: str
    vocab_size: int = 16

config = ConfigWithKwargs(model_type="bert", vocab_size=30000, extra_field="extra_value")
print(config)  # ConfigWithKwargs(model_type='bert', vocab_size=30000, *extra_field='extra_value')

Các đối số từ khóa bổ sung xuất hiện trong biểu diễn chuỗi của dataclass nhưng được thêm tiền tố * để nhấn mạnh rằng chúng không được kiểm tra.

Tích hợp với Type Hints

Strict dataclasses tuân thủ các type hints và tự động kiểm tra chúng. Ví dụ:

from typing import List
from dataclasses import dataclass
from huggingface_hub.dataclasses import strict

@strict
@dataclass
class Config:
    layers: List[int]

config = Config(layers=[64, 128])  # Valid
config = Config(layers="not_a_list")  # Raises StrictDataclassFieldValidationError

Các kiểu được hỗ trợ bao gồm:

  • Bất kỳ
  • Union
  • Tùy chọn
  • Literal
  • Danh sách
  • Dict
  • Tuple
  • Đặt

Và bất kỳ sự kết hợp nào của các kiểu này. Nếu bạn cần xác thực kiểu phức tạp hơn, bạn có thể thực hiện thông qua một bộ xác thực tùy chỉnh.

Trình xác thực lớp

Các phương thức có tên validate_xxx được coi là bộ xác thực lớp. Các phương thức này chỉ được phép nhận self làm đối số. Bộ xác thực lớp được chạy một lần trong quá trình khởi tạo, ngay sau __post_init__. Bạn có thể định nghĩa bao nhiêu bộ xác thực như vậy cũng được—chúng sẽ được thực thi tuần tự theo thứ tự xuất hiện.

Lưu ý rằng các bộ xác thực lớp (class validators) không được tự động chạy lại khi một trường được cập nhật sau khi khởi tạo. Để xác thực lại đối tượng thủ công, bạn cần gọi obj.validate().

from dataclasses import dataclass
from huggingface_hub.dataclasses import strict

@strict
@dataclass
class Config:
    foo: str
    foo_length: int
    upper_case: bool = False

    def validate_foo_length(self):
        if len(self.foo) != self.foo_length:
            raise ValueError(f"foo must be {self.foo_length} characters long, got {len(self.foo)}")

    def validate_foo_casing(self):
        if self.upper_case and self.foo.upper() != self.foo:
            raise ValueError(f"foo must be uppercase, got {self.foo}")

config = Config(foo="bar", foo_length=3) # ok

config.upper_case = True
config.validate() # Raises StrictDataclassClassValidationError

Config(foo="abcd", foo_length=3) # Raises StrictDataclassFieldValidationError
Config(foo="Bar", foo_length=3, upper_case=True) # Raises StrictDataclassFieldValidationError

Phương thức .validate() là một tên được dành riêng cho các dataclass nghiêm ngặt. Để ngăn chặn các hành vi không mong muốn, một lỗi StrictDataclassDefinitionError sẽ được ném ra nếu lớp của bạn đã định nghĩa phương thức này.

Tham khảo API

@strict

Trình trang trí @strict tăng cường cho một dataclass với tính năng xác thực nghiêm ngặt.

huggingface_hub.dataclasses.strict

< >

( accept_kwargs: bool = False )

Tham số

  • cls — Lớp cần chuyển đổi thành strict dataclass.
  • accept_kwargs (bool, tùy chọn) — Nếu là True, cho phép các đối số từ khóa tùy ý trong __init__. Mặc định là False.

Trình trang trí để thêm xác thực nghiêm ngặt vào một dataclass.

Trình trang trí này phải được sử dụng phía trên @dataclass để đảm bảo các IDE và công cụ kiểm tra kiểu tĩnh nhận diện lớp đó là một dataclass.

Có thể được sử dụng có hoặc không có đối số:

  • @strict
  • @strict(accept_kwargs=True)

Ví dụ:

>>> from dataclasses import dataclass
>>> from huggingface_hub.dataclasses import as_validated_field, strict, validated_field

>>> @as_validated_field
>>> def positive_int(value: int):
...     if not value >= 0:
...         raise ValueError(f"Value must be positive, got {value}")

>>> @strict(accept_kwargs=True)
... @dataclass
... class User:
...     name: str
...     age: int = positive_int(default=10)

# Initialize
>>> User(name="John")
User(name='John', age=10)

# Extra kwargs are accepted
>>> User(name="John", age=30, lastname="Doe")
User(name='John', age=30, *lastname='Doe')

# Invalid type => raises
>>> User(name="John", age="30")
huggingface_hub.errors.StrictDataclassFieldValidationError: Validation error for field 'age':
    TypeError: Field 'age' expected int, got str (value: '30')

# Invalid value => raises
>>> User(name="John", age=-1)
huggingface_hub.errors.StrictDataclassFieldValidationError: Validation error for field 'age':
    ValueError: Value must be positive, got -1

validate_typed_dict

Phương thức để xác minh rằng một từ điển tuân thủ các kiểu được định nghĩa trong lớp TypedDict.

Đây là tương đương của việc xác thực dataclass nhưng dành cho TypedDict. Vì typed dict không bao giờ được khởi tạo (chỉ được sử dụng bởi trình kiểm tra kiểu tĩnh), bước xác thực phải được gọi thủ công.

huggingface_hub.dataclasses.validate_typed_dict

< >

( schema: typedata: dict )

Tham số

  • schema (type[TypedDictType]) — Lớp TypedDict định nghĩa cấu trúc và các kiểu dữ liệu mong đợi.
  • data (dict) — Từ điển cần kiểm tra.

Gây ra

StrictDataclassFieldValidationError

  • StrictDataclassFieldValidationError — Nếu bất kỳ trường nào trong từ điển không tuân thủ kiểu dữ liệu mong đợi.

Kiểm tra xem một từ điển có tuân thủ các kiểu được định nghĩa trong lớp TypedDict hay không.

Bên trong, typed dict được chuyển đổi thành một dataclass nghiêm ngặt và được xác thực bằng decorator @strict.

Ví dụ:

>>> from typing import Annotated, TypedDict
>>> from huggingface_hub.dataclasses import validate_typed_dict

>>> def positive_int(value: int):
...     if not value >= 0:
...         raise ValueError(f"Value must be positive, got {value}")

>>> class User(TypedDict):
...     name: str
...     age: Annotated[int, positive_int]

>>> # Valid data
>>> validate_typed_dict(User, {"name": "John", "age": 30})

>>> # Invalid type for age
>>> validate_typed_dict(User, {"name": "John", "age": "30"})
huggingface_hub.errors.StrictDataclassFieldValidationError: Validation error for field 'age':
    TypeError: Field 'age' expected int, got str (value: '30')

>>> # Invalid value for age
>>> validate_typed_dict(User, {"name": "John", "age": -1})
huggingface_hub.errors.StrictDataclassFieldValidationError: Validation error for field 'age':
    ValueError: Value must be positive, got -1

as_validated_field

Decorator để tạo một validated_field. Được khuyến nghị cho các trường có một validator duy nhất để tránh mã lặp lại.

huggingface_hub.dataclasses.as_validated_field

< >

( validator: Callable )

Tham số

  • validator (Callable) — Một phương thức nhận một giá trị làm đầu vào và gây ra ValueError/TypeError nếu giá trị đó không hợp lệ.

Trang trí một hàm validator như một validated_field (tức là một trường dataclass có validator tùy chỉnh).

validated_field

Tạo một trường dataclass với xác thực tùy chỉnh.

huggingface_hub.dataclasses.validated_field

< >

( validator: list[collections.abc.Callable[[typing.Any], None]] | collections.abc.Callable[[typing.Any], None]default: typing.Any = <dataclasses._MISSING_TYPE object at 0x7f9675fda620>default_factory: typing.Any = <dataclasses._MISSING_TYPE object at 0x7f9675fda620>init: bool = Truerepr: bool = Truehash: bool | None = Nonecompare: bool = Truemetadata: dict | None = None**kwargs: typing.Any )

Tham số

  • validator (Callable hoặc list[Callable]) — Một phương thức nhận một giá trị làm đầu vào và gây ra ValueError/TypeError nếu giá trị đó không hợp lệ. Có thể là một danh sách các validator để áp dụng nhiều kiểm tra.
  • **kwargs — Các đối số bổ sung để truyền cho dataclasses.field().

Tạo một trường dataclass với bộ xác thực tùy chỉnh.

Có ích khi áp dụng nhiều kiểm tra cho một trường. Nếu chỉ áp dụng một quy tắc, hãy xem trang trí as_validated_field.

Lỗi

lớp huggingface_hub.errors.StrictDataclassError

< >

( )

Ngoại lệ cơ bản cho các dataclass nghiêm ngặt.

lớp huggingface_hub.errors.StrictDataclassDefinitionError

< >

( )

Lỗi ngoại lệ được ném ra khi một dataclass nghiêm ngặt được định nghĩa không chính xác.

lớp huggingface_hub.errors.StrictDataclassFieldValidationError

< >

( field: strcause: Exception )

Ngoại lệ được ném ra khi một dataclass nghiêm ngặt không vượt qua kiểm tra xác thực cho một trường nhất định.

Tại sao không dùng pydantic? (hay attrs? hay marshmallow_dataclass?)

  • Xem thảo luận tại https://github.com/huggingface/transformers/issues/36329 về việc thêm Pydantic làm một dependency. Đây sẽ là một bổ sung nặng và đòi hỏi logic cẩn thận để hỗ trợ cả v1 và v2.
  • Chúng ta không cần hầu hết các tính năng của Pydantic, đặc biệt là những tính năng liên quan đến chuyển đổi kiểu tự động, jsonschema, chuỗi hóa, alias, v.v.
  • Chúng ta không cần khả năng khởi tạo một lớp từ một từ điển.
  • Chúng ta không muốn thay đổi dữ liệu. Trong @strict, “validation” có nghĩa là “kiểm tra xem một giá trị có hợp lệ hay không.” Trong Pydantic, “validation” có nghĩa là “chuyển đổi kiểu một giá trị, có thể làm thay đổi nó, rồi sau đó kiểm tra xem nó có hợp lệ hay không.”
  • Chúng ta không cần kiểm tra cực kỳ nhanh. @strict không được thiết kế cho các tải nặng mà hiệu suất là yếu tố then chốt. Các trường hợp sử dụng phổ biến bao gồm kiểm tra cấu hình mô hình (được thực hiện một lần và không đáng kể so với việc chạy mô hình). Điều này cho phép chúng ta giữ mã ở mức tối giản.
Update on GitHub