简体   繁体   English

通过self .__ setattr__进行迭代生成的实例属性。 有没有更好的办法?

[英]Instance attributes, generated from iterable with self.__setattr__. Is there a better way?

When you setting attributes to an instance from some iterable like this: 当您从一些可迭代的实例中为实例设置属性时:

class DogWith100Legs():
    def __init__(self, legs_colors):
        for leg_i, color in legs_colors.items():
            self.__setattr__(leg_i, color)

legs_colors = {'leg_1': 'white', 'leg_2': 'brown', ... , 'leg_100': 
'black'}
doge = DogWith100Legs(legs_colors)
print(doge.leg_100)

it works fine. 它工作正常。 But PyCharm will highlight leg_100 with a warning: "Unresolved reference 'leg_100' for class 'DogWith100Legs'. 但是PyCharm会突出显示leg_100并显示警告:“类'DogWith100Legs'的未解析引用'leg_100'。

Why i want to do this? 为什么我要这样做? I want to create tree-like object. 我想创建树状对象。 Like BeautifulSoup do. 就像BeautifulSoup一样。 But bs4 does not have such a problem in PyCharm 但是bs4在PyCharm中没有这样的问题

Also, there are comments in similar questions (like PyCharm warns about unresolved attribute for dict generated attributes ), where people say, that it is a bad practice 另外,在类似的问题中也有评论(例如PyCharm警告dict生成的属性有未解决的属性 ),人们说这是一种不良做法

What will be a good practice? 有什么好的做法? Or may be you know a good way to calm down Pycharm? 也许您知道平息Pycharm的好方法吗? (Not disabling Pycharm check) (不禁用Pycharm检查)

PyCharm (and every other IDE) will give you warnings/errors because in __init__ you have to declare every member of the object. PyCharm(以及所有其他IDE)将给您警告/错误,因为在__init__您必须声明该对象的每个成员。

Because you are passing a dict, probably the best thing to do is to instantiate a dict into your class too, and then just get the value you need with the key self.my_dict['leg_x'] and not self.leg_x . 因为您要传递一个dict,所以最好的办法就是也将dict实例化到您的类中,然后仅通过键self.my_dict['leg_x']而不是self.leg_x获得所需的值。

class DogWith100Legs():
def __init__(self, legs_colors):
    self.legs_colors = legs_colors.copy()

legs_colors = {'leg_1': 'white', 'leg_2': 'brown', 'leg_100': 'black'}
doge = DogWith100Legs(legs_colors)
print(doge.legs_colors['leg_100'])

It depends on intended usage. 这取决于预期用途。

1 If you are going to access the data directly by name, and there is no obvious relationship between items. 1如果您要直接通过名称访问数据,并且项目之间没有明显的关系。

print(dog.leg_32)
print(dog.leg_5)

Only in this case is __setattr__ fine. 仅在这种情况下__setattr__可以。

2 You plan to retrieve the data indirectly, and/or there is some relationship (eg previous, next): 2您计划间接检索数据,并且/或者存在某种关系(例如,上一个,下一个):

i = 25
print(dog.leg[i])
print(dog.leg[i+1])

In this case all data should be placed into a container ( list , dict are the most common ones). 在这种情况下,所有数据都应放入容器中( listdict是最常见的数据)。 Most probably this is what you want. 这很可能就是您想要的。

I would rethink what you are trying to do a little bit - maybe even check out the BeautifulSoup source code to see how they do it. 我会重新考虑您要尝试做些什么-甚至可以查看BeautifulSoup源代码以了解他们是如何做到的。

In general though, there is no reason (that I can think of) to dynamically define instance attributes like this. 但总的来说,没有理由(我能想到)动态定义这样的实例属性。 You should simply have a leg dictionary or list within your Dog objects, like so: 您应该只在Dog对象中包含一个leg字典或列表,如下所示:

def __init__(self, legs_colors: dict):
    self.legs_colors = legs_colors.copy()

Instance attributes should be individually important, but I doubt that you plan to use leg_1 differently than you plan to use leg_72 , especially since you can't guarantee that either of these attributes will exist with the way you have defined __init__ . 实例属性应该是个别重要的,但我怀疑你计划使用leg_1比你计划使用不同leg_72 ,特别是因为你不能保证这两种属性将与您所定义的方式存在__init__

Also, when you later access these leg attributes, you will likely want to do so dynamically. 另外,当您以后访问这些支腿属性时,您可能希望动态地进行操作。 In which case you would have to resort to something like: 在这种情况下,您将不得不诉诸以下内容:

for leg in [f'leg_{i}' for i in range(100)]
    color = getattr(doge, leg)
    # do something with leg and color

instead of the simpler, clearer, and less smelly: 而不是更简单,更清晰,更不臭:

for leg, color in doge.legs_colors.items():
    # do something with leg and color

You can still program different interfaces for accessing your legs_colors dictionary, if you'd like to. 如果愿意,您仍然可以编写其他接口来访问legs_colors字典。 For example, you could overwrite __getitem__ on your Dog class if you want to be able to do doge[i] directly. 例如,如果您想直接执行doge[i] ,则可以在Dog类上覆盖__getitem__

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 __setattr__ 禁止更改实例/自变量? - __setattr__ to prohibit changes to instance/self variables? 在文本文件中存储Python实例属性的更好方法是什么? - What is a better way to store Python instance attributes in a text file? Python:如何返回 object 的实例以及使用 setattr 分配的属性 - Python: How to return an instance of an object along with attributes assigned with setattr 使用object .__ setattr __(self,…,…)`而不是`setattr(self,…,…)`? - `object.__setattr__(self, …, …)` instead of `setattr(self, …, …)`? 使用id(self)缓存属性,还有更好的解决方案吗? - Caching attributes with id(self), any better solutions? 在返回“自我”之前调用setattr - calling setattr before 'self' is returned 从Django查询集中仅获取特定属性的更好方法? - A better way to get only specific attributes from a Django queryset? 通过__setattr__分配时,Python属性设置未分配正确的实例属性(下划线) - Python property setting does not assign the right instance attributes (leading underscores) when assigning via __setattr__ 在python中重写__setattr__和__getattribute__时,无法更新可变实例属性 - Cannot update mutable instance attributes when __setattr__ and __getattribute__ are overridden in python 使用setattr()更新对象实例 - Using setattr() to update an object instance
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM