简体   繁体   English

导入和使用数据作为对象属性的Python方法

[英]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: 我有一个例子如下:

defining data class 定义数据类别

class ImportData:
    def __init__(self, path):
        # open file and assign to some variables
        # such as:
        self.slope = 1
        self.intercept = -1

solution 1: use composition 解决方案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))

solution 2: use inheritance 解决方案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 . 您认为组合解决方案中的链接属性访问是代码气味,这是正确的: dataObj的实现细节,应该对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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM