[英]Pythonic way to import and use data as object attributes
I am working with data that is used as variables after they are imported. 导入后,我正在使用用作变量的数据。 I would like to then use the variables in an object as attributes.
然后,我想将对象中的变量用作属性。
So far I have accomplished this by writing an ImportData class and then it is composed into another class, Obj, that uses it for other calculations. 到目前为止,我已经通过编写ImportData类完成了此工作,然后将其组合到另一个类Obj中,该类将其用于其他计算。 Another solution i have used, is to inherit from the ImportData class.
我使用的另一种解决方案是从ImportData类继承。 I have an example below:
我有一个例子如下:
class ImportData:
def __init__(self, path):
# open file and assign to some variables
# such as:
self.slope = 1
self.intercept = -1
class Obj:
def __init__(self, data_object):
self.data = data_object
def func(self, x):
return self.data.slope*x + self.data.intercept
data_object = ImportData('<path>')
obj = Obj(data_object)
# get the slope and intercept
print('slope =', obj.data.slope, ' intercept =', obj.data.intercept)
# use the function
print('f(2) =', obj.func(2))
class Obj(ImportData):
def __init__(self,path):
super().__init__(path)
def func(self, x):
return self.slope*x + self.intercept
obj = Object('<path>')
# get the slope and intercept
print('slope =', obj.slope, ' intercept =', obj.intercept)
# use the function
print('f(2) =', obj.func(2))
I don't like the composition solution because I have to type an extra "data" every time I need to access an attribute but I'm not sure inheritance is the right way to go either. 我不喜欢组合解决方案,因为每次需要访问属性时都必须键入一个额外的“数据”,但是我不确定继承是否是正确的选择。
Am I out in left field and there is better solution? 我是否在左场,还有更好的解决方案?
Your sense that the chained attribute access in the composed solution is a code smell is correct: data
is an implementation detail of Obj
and should be hidden from Obj
's clients, so if the implementation of the ImportData
class change, you only have to change Obj
and not every class that calls obj.data
. 您认为组合解决方案中的链接属性访问是代码气味,这是正确的:
data
是Obj
的实现细节,应该对Obj
的客户端隐藏,因此,如果ImportData
类的实现更改,则只需更改Obj
而不是每一个类调用obj.data
。
We can hide Obj.data
by giving Obj
a __getattr__
method to control how its attributes are accessed. 我们可以通过为
Obj
提供__getattr__
方法来控制如何访问其属性来隐藏Obj.data
。
>>> class ImportData:
... def __init__(self, path):
... self.slope = 1
... self.intercept = -1
...
>>> data = ImportData()
>>> class Obj:
... def __init__(self, data_object):
... self.data = data_object
... def func(self, x):
... return self.slope*x + self.intercept
... def __getattr__(self, name):
... try:
... return getattr(self.data, name)
... except AttributeError:
... raise AttributeError('{} object has no attribute {}.'.format(self.__class__.__name__, name))
>>> o = Obj(data)
>>> o.func(2)
1
>>> o.slope
1
>>> o.intercept
-1
>>>
Normally, if python fails to find an attribute of an object - for example obj.slope
- it will raise an AttributeError
. 通常,如果python无法找到对象的属性(例如
obj.slope
),它将引发AttributeError
。 However if the object has a __getattr__
method python will call __getattr__
instead of raising an exception. 但是,如果对象具有
__getattr__
方法,则python将调用__getattr__
而不是引发异常。
In the above code, Obj.__getattr__
looks for the attribute on data
if it doesn't exist on Obj
, so Obj
's clients can call obj.slope
instead of obj.data.slope
. 在上面的代码中,如果
Obj
不存在,则Obj.__getattr__
在data
上查找属性,因此Obj
的客户端可以调用obj.slope
而不是obj.data.slope
。 The re-raising of AttributeError
is done so that the error message refers to Obj
rather than ImportData
完成
AttributeError
的重新引发,以便错误消息引用的是Obj
而不是ImportData
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.