【问题标题】:How to make immutable attributes in class?如何在类中制作不可变属性?
【发布时间】:2021-06-20 10:49:19
【问题描述】:

问题:我正在创建一个具有属性的类。其中一些应该只是可读的,而有些应该在尝试打印出来时完全无法访问。我正在尝试通过__setattribute____getattribute__ 函数来实现它(我只是想不出更好的方法来做到这一点,如果您对如何改进它有任何建议,我将不胜感激)。问题是,虽然__getattribute__ 函数工作得非常好并引发了所需的异常,但__setattribute__ 却没有。程序只是通过它。

代码:

class Fruit:
  def __setattribute__(self, name, value):
    if name in ('exp_date'):
      raise AttributeError('Unable to edit')
    return __setattribute__(self, name, value)
  def __getattribute__(self, name):
        if name in ('subtype'):
            raise AttributeError('Unable to view this object')
        return __getattribute__(self, name)
  def __init__(self, sub:str = None, col:str = None, expd:int = None, pkp:int = None, amount:int = None):
    self.color, self.price_per_kilo = col, pkp
    self.amount = amount
    self.exp_date = expd
    self.subtype = sub
  def estimaterevenue(self):
    return self.price_per_kilo * self.amount

测试:

fruit= Fruit()
fruit.exp_date = 123 # __set__ is being passed for some reason
print(fruit.subtype) # AttributeError: Unable to view this object

【问题讨论】:

  • fruit.exp_date = 123 会调用__setattribute__ 而不是__set__
  • @rdas 抱歉,版本错误,我已对帖子进行了编辑
  • 你的答案不是在这里吗? stackoverflow.com/questions/7042152/…
  • ('exp_date') 不是一个元组,顺便说一句。它只是一个字符串。

标签: python oop


【解决方案1】:

__get_attribute____set_attr_ 比较难理解,最好使用简单的属性:

class Fruit:
    def __init__(self, subtype=None, color=None, exp_date=None, price_per_kilo=None, amount=None):
        self.color = color
        self.price_per_kilo = price_per_kilo
        self.amount = amount
        self._exp_date = exp_date
        self._subtype = subtype

    def estimaterevenue(self):
        return self.price_per_kilo * self.amount

    @property
    def exp_date(self):
        return self._exp_date
    

fruit= Fruit()
fruit.exp_date = 123 # AttributeError 
print(fruit.subtype) # AttributeError: Unable to view this object

【讨论】:

  • 是的,但他仍然可以做到fruit._subtype
【解决方案2】:

对于定义了哪些 dunder 方法似乎有些混淆。我也不知道,但我认为这可以满足您的要求:

class Fruit:
    def __setattr__(self, name, value):
        print('set attribute', name)
        if name in ('exp_date'):
            raise AttributeError('Unable to edit')
        return super().__setattr__(name, value)

更新:

上面的代码不起作用,因为exp_date不能在__init__()中设置。

这段代码可以解决这个问题:

class Fruit:
  def __setattr__(self, name, value):
    #print('set attribute', name)
    if name in 'attr_gate' or self.attr_gate or name not in 'exp_date':
        return super().__setattr__(name, value)
    raise AttributeError('Unable to edit')
  def __getattribute__(self, name):
        #print('get attribute', name)
        if name in ('subtype'):
            raise AttributeError('Unable to view this object')
        return super().__getattribute__(name)
  def __init__(self, sub:str = None, col:str = None, expd:int = None, pkp:int = None, amount:int = None):
    self.attr_gate = True
    self.color, self.price_per_kilo = col, pkp
    self.amount = amount
    self.exp_date = expd
    self.subtype = sub
    self.attr_gate = False

【讨论】:

  • 尝试在构造函数中设置属性时不会出现问题吗?
【解决方案3】:

以下实现使用一个计数器,因此您可以在构造函数中设置一次值,但不能随后设置。

class Fruit: 
  def __setattr__(self, name, value): 
    if name in ('exp_date') and self.count_exp_date>=1: 
      raise AttributeError('Unable to edit') 
    # return __setattribute__(self, name, value) 
    if name in ('exp_date'): 
        self.count_exp_date+=1 
    super().__setattr__(name, value)  
  def __getattribute__(self, name): 
        if name in ('subtype'): 
            raise AttributeError('Unable to view this object') 
        return super().__getattribute__(name) 
  def __init__(self, sub:str = None, col:str = None, expd:int = None, pkp:int = None, amount:int = None): 
    self.count_exp_date = 0 
    self.color, self.price_per_kilo = col, pkp 
    self.amount = amount 
    self.exp_date = expd 
    self.subtype = sub 
  def estimaterevenue(self): 
    return self.price_per_kilo * self.amount 

【讨论】:

    猜你喜欢
    • 2017-09-15
    • 1970-01-01
    • 2010-11-29
    • 2011-07-08
    • 2021-01-15
    • 2014-02-20
    • 2019-09-04
    相关资源
    最近更新 更多