【问题标题】:__slots__ and unbound methods__slots__ 和未绑定的方法
【发布时间】:2012-07-26 13:42:27
【问题描述】:

我在插槽方面需要一点帮助。

class bstream(object):
  __slots__ = ['stream']
  stream = string()

  def __new__(self, stream, encoding=None):
    if encoding == None:
      encoding = ENCODING['default']
    if isinstance(stream, bytes):
      self.stream = stream.decode(encoding)
    elif isinstance(stream, string):
      self.stream = stream
    else: # if unknown type
      strtype = type(stream).__name__
      raise(TypeError('stream must be bytes or string, not %s' % strtype))
    return(self)

  def __repr__(self):
    '''bstream.__repr__() <==> repr(bstream)'''
    chars = ['\\x%s' % ('%02x' % ord(char)).upper() for char in self.stream]
    result = ''.join(chars)
    return(result)

  def func(self):
    return(1)

不要与那些字符串类型和 ENCODINGS 字典混淆:它们是常量。 问题是以下命令无法按我的预期工作:

>>> var = bstream('data')
>>> repr(var)
<class '__main__.bstream'> # Instead of '\\x64\\x61\\x74\\x61'
>>> var.func()
TypeError: unbound method func() must be called with bstream instance as first argument (got nothing instead)

怎么了?我真的很想让我的班级不可变,所以删除 slots 的解决方案真的不是很好。 :-) 非常感谢!

【问题讨论】:

  • 为什么? __slots__ 相当没用,尤其是在您知道自己需要它之前。这是使您的类不可变的一种糟糕方法,为此,不要对其进行变异(或不提供公共 API 来对其进行变异)。
  • @Julian:你说得对,我已经将它定义为使类不可变。之前我总是使用 Cython 做同样的事情,但它不像 Python 那样可移植。
  • 为什么你希望类是不可变的?如果您不想更改,请不要更改它。你正在努力对抗 Python。
  • 看看this answer,你可能不想要__slots__,我也真的不认为你想要__new__
  • @D.Shawley:它已经在 Python 3 中了。我使用它是因为它仍然是用户尝试设置属性时避免错误的最佳方法。这也是减少 Python 在处理对象时所需内存的好方法。

标签: python class immutability slots


【解决方案1】:

您想使用__init__,而不是__new__

__new__ 是一个类方法,它的第一个参数(self)是 class 对象,而不是新创建的对象。它必须返回新对象。你通常不想重新定义它,但如果你想做一些事情,比如返回一个现有的对象,你可以这样做。

__init__是一个常规的实例方法,第一个参数(self)是新创建的实例。它的工作方式与其他语言中的构造函数类似。

要解决此问题,请将方法名称更改为 __init__ 并删除最后一行 (return(self))。 __init__。必须始终返回None;返回任何其他内容都会导致 TypeError

【讨论】:

  • 这会在创建对象时引发错误:AttributeError: 'bstream' object attribute 'stream' is read-only
  • 好的,我已经解决了:我只需要在__slots__ = ['stream'] 之后删除stream = string()。谢谢!
猜你喜欢
  • 2017-11-06
  • 2015-09-12
  • 2013-12-25
  • 1970-01-01
  • 2010-11-04
  • 1970-01-01
  • 2016-05-19
  • 2011-04-03
相关资源
最近更新 更多