Skip to main content
 首页 » 编程设计

python之使用类型和 __slots__ 动态创建类

2025年05月04日10soundcode

在类中创建结果对象时,是否可以在本例中使用__slots__?我想我可以通过将 '__slots__' 传递到 type 的第三个参数的字典中来让它工作:

class GeocodeResult(object): 
    """class to handle Reverse Geocode Result""" 
 
    __slots__ = ['geometry', 'response', 'spatialReference', 
                'candidates', 'locations', 'address', 'type', 'results'] 
 
    def __init__(self, res_dict, geo_type): 
        RequestError(res_dict) 
        self.response = res_dict 
        self.type = 'esri_' + geo_type 
        self.spatialReference = None 
        self.candidates = [] 
        self.locations = [] 
        self.address = [] 
        if 'spatialReference' in self.response: 
            self.spatialReference = self.response['spatialReference'] 
 
        # more stuff 
 
    @property 
    def results(self): 
        results = [] 
        for result in self.address + self.candidates + self.locations: 
            result['__slots__'] = ['address', 'score', 'location', 'attributes'] 
            results.append(type('GeocodeResult.result', (object,), result)) 
        return results 
 
    def __len__(self): 
        """get length of results""" 
        return len(self.results) 

对于 results 属性,我想构建一个包含 4 个属性的小型轻量级对象列表:['address', 'score', 'location', 'attributes ']

生成的对象已创建,我什至可以获取插槽,但它仍然保留 __dict__。由于可能有数百个结果对象,我只需要上面列出的四个属性以节省空间。

例子:

>>> rev = GeocodeResult(r, 'reverseGeocode') 
>>> result = rev.results[0] 
>>> result.__slots__ 
['address', 'score', 'location', 'attributes'] 
>>> hasattr(result, '__dict__') 
True 
>>>  

有更好的方法吗?或者我是否必须定义一个明确的类来处理这个?

请您参考如下方法:

动态创建带槽的类是完全可能的:

>>> C = type('C', (), {'__slots__': ('a', 'b')}) 
>>> C.a 
<member 'a' of 'C' objects> 
>>> dir(C()) 
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'a', 'b'] 
>>> vars(C()) 
Traceback (most recent call last): 
  ... 
TypeError: vars() argument must have __dict__ attribute 

适用于 Python 3 和 2。

您在示例中看到 hasattr(result, '__dict__') 评估 True 因为 GecodeResult.results 返回的列表是类型列表,而不是实例列表。如果你说 result().__dict__,你会得到一个 AttributeError。

(还值得注意:该列表中的每种类型共享名称“GeocodeResult.result”,但它们不是同一类型!results[0].__class__ == results[ 1].__class__ 是 False。)

正如 jonrsharpe 指出的那样,最好只定义一次类型并重用它,而 namedtuple 非常适合这项工作,所以坚持使用它:)