我想知道初始化类成员的python方法是什么,但只有在访问它时才会访问它.我尝试了下面的代码并且它正在运行,但有什么比这简单吗?
class MyClass(object):
_MY_DATA = None
@staticmethod
def _retrieve_my_data():
my_data = ... # costly database call
return my_data
@classmethod
def get_my_data(cls):
if cls._MY_DATA is None:
cls._MY_DATA = MyClass._retrieve_my_data()
return cls._MY_DATA
Run Code Online (Sandbox Code Playgroud) 举一个简单的例子,取一个可以返回其属性的class 椭圆,例如面积A,周长C,长轴/短轴a/b,偏心率e等.为了得到它,显然必须提供其两个参数以获得所有其他参数,虽然作为一个特殊情况,只提供一个参数应该假设一个圆圈.三个或更多一致的参数应该产生警告但是有效,否则显然会引发异常.
所以有效Ellipses的一些例子是:
Ellipse(a=5, b=2)
Ellipse(A=3)
Ellipse(a=3, e=.1)
Ellipse(a=3, b=3, A=9*math.pi) # note the consistency
Run Code Online (Sandbox Code Playgroud)
而无效的将是
Ellipse()
Ellipse(a=3, b=3, A=7)
Run Code Online (Sandbox Code Playgroud)
因此构造函数要么包含许多=None参数,
class Ellipse(object):
def __init__(self, a=None, b=None, A=None, C=None, ...):
Run Code Online (Sandbox Code Playgroud)
或者,可能更明智,一个简单的**kwargs,可能添加提供a,b作为位置参数的选项,
class Ellipse(object):
def __init__(self, a=None, b=None, **kwargs):
kwargs.update({key: value
for key, value in (('a', a), ('b', b))
if value is not None})
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.但现在实际实现,即确定提供哪些参数,哪些参数不是,并根据它们确定所有其他参数,或在需要时检查一致性.
我的第一种方法是许多人的简单而乏味的组合
if 'a' in kwargs:
a = kwargs['a'] …Run Code Online (Sandbox Code Playgroud) 我试图多次使用类方法的结果,而不进行获得结果所需的繁重计算。
我看到以下选项。你认为哪些是正确的,或者更像 Pythonic?
每一种的优点和缺点是什么?
class Test:
def __init__(self, *args):
# do stuff
@property
def new_method(self):
try:
return self._new_property
except AttributeError:
# do some heavy calculations
return self._new_property
Run Code Online (Sandbox Code Playgroud)
from functools import lru_cache
class Test:
def __init__(self, *args):
# do stuff
@property
@lru_cache()
def new_method(self):
# do some heavy calculations
return self._new_property
Run Code Online (Sandbox Code Playgroud)
from django.utils.functional import cached_property
class Test:
def __init__(self, *args):
# do stuff
@cached_property
def new_method(self):
# do some heavy calculations
return self._new_property
Run Code Online (Sandbox Code Playgroud) 我有使用@property装饰器设置属性的类.它们使用try和except子句作为getter和setter.如果未设置attribute,它将从数据库获取数据并使用它来从其他类中实例化对象.我试图保持示例简短,但用于实例化属性对象的代码与每个属性略有不同.他们的共同点是尝试 - 开头时除外.
class SubClass(TopClass):
@property
def thing(self):
try:
return self._thing
except AttributeError:
# We don't have any thing yet
pass
thing = get_some_thing_from_db('thing')
if not thing:
raise AttributeError()
self._thing = TheThing(thing)
return self._thing
@property
def another_thing(self):
try:
return self._another_thing
except AttributeError:
# We don't have things like this yet
pass
another_thing = get_some_thing_from_db('another')
if not another_thing:
raise AttributeError()
self._another_thing = AnotherThing(another_thing)
return self._another_thing
...etc...
@property
def one_more_thing(self):
try:
return self._one_more_thing
except AttributeError:
# We don't have this …Run Code Online (Sandbox Code Playgroud) 我想复制冻结数据类的实例,仅更改一个字段(“功能更新”)。
这是我尝试过的
from dataclasses import dataclass, asdict
@dataclass(frozen = True)
class Pos:
start: int
end: int
def adjust_start(pos: Pos, delta: int) -> Pos:
# TypeError: type object got multiple values for keyword argument 'start'
return Pos(**asdict(pos), start = pos.start + delta)
adjust_start(Pos(1, 2), 4)
Run Code Online (Sandbox Code Playgroud)
我正在寻找什么:
dicts 转换更直接的方法?TypeError:如果有一种方法可以在功能上更新 kwargs,那么这是可行的。在 Scala 中,案例类(Scala 数据类)的功能更新可以这样完成pos.copy(start = pos.start + delta):
我有以下示例:
class A:
value = None
@property
def value(self):
if not value:
result = <do some external call>
self.value = result
return self.value
Run Code Online (Sandbox Code Playgroud)
但是,由于我收到异常,因此无效:
AttributeError: can't set attribute
Run Code Online (Sandbox Code Playgroud)
这是有道理的,但做这样的事情的惯用方法是什么?我不只是想使用不同的名字.