Они весьма схожи, и строки между ними являются довольно серыми. Я предполагаю, что Вы читаете записи Шаблона "декоратор" Шаблона "proxy" и в c2 wiki.
записи и обсуждения там довольно обширны, и они также связываются с другими соответствующими статьями. Между прочим, c2 wiki превосходен при удивлении о нюансах между различными шаблонами.
Для подведения c2 записей я сказал бы, что декоратор добавляет/изменяет поведение, но прокси больше имеет отношение к управлению доступом (ленивое инстанцирование, удаленный доступ, безопасность и т.д.). Но как я сказал, строки между ними являются серыми, и я вижу ссылки на прокси, которые могли легко быть просмотрены как декораторы и наоборот.
dict
у меня есть библиотека с открытым исходным кодом, где я делаю вещи в функциональный способ, которым настолько перемещающиеся данные в неизменном объекте полезны. Однако я не хочу должным быть преобразовывать свой объект данных для клиента взаимодействовать с ними. Так, я придумал это - это дает Вам dict как объект, это неизменно + некоторые вспомогательные методы.
Кредит к Sven Marnach в его ответ для базового внедрения ограничения обновления свойства и удаления.
import json
# ^^ optional - If you don't care if it prints like a dict
# then rip this and __str__ and __repr__ out
class Immutable(object):
def __init__(self, **kwargs):
"""Sets all values once given
whatever is passed in kwargs
"""
for k,v in kwargs.items():
object.__setattr__(self, k, v)
def __setattr__(self, *args):
"""Disables setting attributes via
item.prop = val or item['prop'] = val
"""
raise TypeError('Immutable objects cannot have properties set after init')
def __delattr__(self, *args):
"""Disables deleting properties"""
raise TypeError('Immutable objects cannot have properties deleted')
def __getitem__(self, item):
"""Allows for dict like access of properties
val = item['prop']
"""
return self.__dict__[item]
def __repr__(self):
"""Print to repl in a dict like fashion"""
return self.pprint()
def __str__(self):
"""Convert to a str in a dict like fashion"""
return self.pprint()
def __eq__(self, other):
"""Supports equality operator
immutable({'a': 2}) == immutable({'a': 2})"""
if other is None:
return False
return self.dict() == other.dict()
def keys(self):
"""Paired with __getitem__ supports **unpacking
new = { **item, **other }
"""
return self.__dict__.keys()
def get(self, *args, **kwargs):
"""Allows for dict like property access
item.get('prop')
"""
return self.__dict__.get(*args, **kwargs)
def pprint(self):
"""Helper method used for printing that
formats in a dict like way
"""
return json.dumps(self,
default=lambda o: o.__dict__,
sort_keys=True,
indent=4)
def dict(self):
"""Helper method for getting the raw dict value
of the immutable object"""
return self.__dict__
def update(obj, **kwargs):
"""Returns a new instance of the given object with
all key/val in kwargs set on it
"""
return immutable({
**obj,
**kwargs
})
def immutable(obj):
return Immutable(**obj)
obj = immutable({
'alpha': 1,
'beta': 2,
'dalet': 4
})
obj.alpha # 1
obj['alpha'] # 1
obj.get('beta') # 2
del obj['alpha'] # TypeError
obj.alpha = 2 # TypeError
new_obj = update(obj, alpha=10)
new_obj is not obj # True
new_obj.get('alpha') == 10 # True
Так, я пишу соответствующий из python 3:
I) с помощью декоратора класса данных и набора frozen=True. мы можем создать неизменные объекты в Python.
, чтобы эта потребность импортировала класс данных из lib классов данных и потребностей установить frozen=True
напр.
от dataclasses импортируют dataclass
@dataclass(frozen=True)
class Location:
name: str
longitude: float = 0.0
latitude: float = 0.0
o/p:
<блок цитирования>л = Местоположение ("Дели", 112.345, 234.788) l.name 'Дели' l.longitude 112.345 l.latitude 234.788 l.name = "Калькутта" dataclasses. FrozenInstanceError: не может присвоить полю 'имя'
блок цитирования>
Для Python 3.7 + можно использовать Класс Данных с frozen=True
опция , которая является очень pythonic и удобный в сопровождении способ сделать то, что Вы хотите.
Это посмотрело бы что-то как этот:
from dataclasses import dataclass
@dataclass(frozen=True)
class Immutable:
a: Any
b: Any
Как в [1 121] вывод подсказок типа требуется для полей dataclasse, я использовал Любой от typing
модуль .
Перед Python 3.7 это было частым, чтобы видеть, что namedtuples используется в качестве неизменных объектов. Это может быть хитро во многих отношениях, один из них - то, что __eq__
метод между namedtuples не рассматривает классы объектов. Например:
from collections import namedtuple
ImmutableTuple = namedtuple("ImmutableTuple", ["a", "b"])
ImmutableTuple2 = namedtuple("ImmutableTuple2", ["a", "c"])
obj1 = ImmutableTuple(a=1, b=2)
obj2 = ImmutableTuple2(a=1, c=2)
obj1 == obj2 # will be True
, Как Вы видите, даже если типы obj1
и obj2
отличаются, даже если названия их полей отличаются, obj1 == obj2
все еще, дает True
. Поэтому __eq__
используемый метод является одним кортежа, который сравнивает только значения полей, учитывая их положения. Это может быть огромным источником ошибок, особенно при разделении на подклассы этих классов.