我需要创建一个描述符,在初始化后将一些类属性变为不可变
我需要创建 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.`
这是
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})"