Я прочитал основные ответы на usage of slots, и он дал мне представление о том, как и где использовать __slots__
.Как использовать `__slots__` с инициализацией атрибутов?
Сейчас я портирования кода из Python 2 на Python 3, который аналогичен следующим образом:
class B(object):
__slots__ = ('_fields')
_fields = set()
Но это дает ошибку Python 3, работая отлично на Python 2:
ValueError: '_fields' in __slots__ conflicts with class variable
.
изменить код
class B(object):
__slots__ = ('_fields')
def __init__(self):
_fields = set()
и она отлично работает. Мой запрос: это даже правильное изменение?
Как я понял из исходного кода, я предполагаю, что он не использует __dict__
для сохранения памяти или более быстрого доступа или по какой-либо причине, но в то же время также пытается указать тип атрибута _field
как установленный() , Может ли это изменение быть правильным способом сказать это или может иметь некоторые побочные эффекты.
Дальнейшие эксперименты: я экспериментировал дальше с следующими вариантами (на Python 3):
import pdb
class A(object):
a = set()
'''
class B(object):
__slots__ = ('a')
a = set()
'''
class C(object):
__slots__ = ('a')
def __init__(self):
a = set()
class D(object):
def __init__(self):
__slots__ = ('a')
a = set()
if __name__ == '__main__':
#pdb.set_trace()
x = A(); print(dir(x))
#y = B()
z = C(); print(dir(z))
z1 = D(); print(dir(z1))
и он дал следующий результат.
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a']
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'a']
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
Мы можем видеть, что только объект С показывает правильный след т.е. не __dict__
и только __slots__
. Разве это не идеальный вариант? Любое объяснение на __weakref__
также было бы полезно.
Также на Python 2 объекты B и C показывают одинаковый след. Исходя из этого, C должен быть правильным способом поставить его, поскольку он компилируется как на Python 2, так и на 3.
Спасибо. Но мы хотели бы сказать следующее в '__init__' вместо ' self._fields = _fields, если не None else set() ' – ViFI
' if not _fields: 'check' _fields' в [boolean контексте] (http: // stackoverflow .com/а/1452500/1431750). Поэтому, если '_fields' является' None', тогда это выражение оценивается как 'True', а строка' self._fields = set() 'выполняется. Он также может быть выполнен как 'if_fields is None: self._fields = set()'. Btw, в примере в вашем комментарии, 'not None' всегда True. Вы можете поместить его как 'self._fields = _fields, если _fields не является None else set()' или более Pythonic 'self._fields = _fields, если _fields else set()'. _Caveat: _ пустой 'set()' вычисляет значение False, поэтому используйте соответствующую проверку ... – aneroid
_Caveat: _ пустой 'set()' оценивает значение False, поэтому используйте другую проверку, если 'set()' в порядке, Нет, нет. Кроме того, не выполняйте функцию или методы intialize с [изменяемыми типами в качестве значений аргументов по умолчанию] (http://stackoverflow.com/q/1132941/1431750); например 'set',' dict', 'list' и т. д. [Другой пример здесь] (http://docs.python-guide.org/en/latest/writing/gotchas/#mutable-default-arguments). – aneroid