创建一个描述符,在初始化后将一些类属性变为不可变

问题描述 投票:0回答:1

我需要创建一个描述符,在初始化后将一些类属性变为不可变

我需要创建 1 个类和 2 个描述符来管理其属性。任务是:

  • 您必须实现具有价格、作者和名称属性的 Book 类。

  • 作者和姓名字段必须是不可变的;

  • 价格字段可能会有变化,但必须在 0 <= price <= 100 range.

  • 如果用户在初始化后尝试更改作者或名称字段或设置价格超出范围,则应引发 ValueError

  • 实现描述符 PriceControl 和 NameControl 来验证参数。*

我已经完成了基本类和价格描述符的代码,但仍坚持作者的观点 我是一个。你能帮我解决这个代码吗?

我的代码是:

class PriceControl:
    """
    Descriptor which don't allow to set price
    less than 0 and more than 100 included.
    """

    def __init__(self):
        self.price = 0

    def __get__(self, instance, owner):
        return self.price

    def __set__(self, instance, value):
        if value < 0 or value > 100:
            raise ValueError('Price must be between 0 and 100.')
        self.price = value
        return self.price


class NameControl:

    """
    Descriptor which don't allow to change field value after initialization.
    """
    pass

    # def __set__(self, obj, value):
    #     if obj or value is None:
    #         return self
    #     elif obj is not None:
    #         raise ValueError(f'ValueError: Author can not be changed.')
    #     elif value is not None:
    #         raise ValueError(f'ValueError: Name can not be changed.')


class Book:
    author = NameControl()
    name = NameControl()
    price = PriceControl()

    def __init__(self, author, name, price):
        vars(self)['author'] = author
        self.name = name
        self.price = price

预期结果是:

>>> b = Book("William Faulkner", "The Sound and the Fury", 12)
>>> print(f"Author='{b.author}', Name='{b.name}', Price='{b.price}'")
Author='William Faulkner', Name='The Sound and the Fury', Price='12'

>>> b.price = 55
>>> b.price
55
>>> b.price = -12  # => ValueError: Price must be between 0 and 100.
>>> b.price = 101  # => ValueError: Price must be between 0 and 100.

>>> b.author = "new author"  # => ValueError: Author can not be changed.
>>> b.name = "new name"      # => ValueError: Name can not be changed.`
python magic-methods descriptor
1个回答
0
投票

这是

Book
类的实现以及两个描述符:

class PriceControl:
    def __set_name__(self, owner, name):
        self.name = name

    def __get__(self, instance, owner):
        return instance.__dict__[self.name]

    def __set__(self, instance, value):
        if not (0 <= value <= 100):
            raise ValueError("Price must be between 0 and 100")
        instance.__dict__[self.name] = value

class NameControl:
    def __set_name__(self, owner, name):
        self.name = name

    def __get__(self, instance, owner):
        return instance.__dict__[self.name]

    def __set__(self, instance, value):
        if instance.__dict__.get(self.name):  # Check if already set
            raise ValueError(f"'{self.name}' attribute is immutable")
        instance.__dict__[self.name] = value

class Book:
    price = PriceControl()
    author = NameControl()
    name = NameControl()

    def __init__(self, price, author, name):
        self.price = price
        self.author = author
        self.name = name

    def __repr__(self):
        return f"Book(author={self.author}, name={self.name}, price={self.price})"
© www.soinside.com 2019 - 2024. All rights reserved.