繁体   English   中英

有什么方法可以获取所有可能的 Python 类变量,包括没有值的变量?

[英]Any way to get all possible Python class variables, including ones without values?

我正在创建一个类来表示查询,如下所示:

class Query:
    height: int
    weight: int
    age: int
    name: str
    is_alive: bool = True

如您所见,一些变量开始时使用默认值进行初始化,而其他变量则没有。

我想像这样实现可链接的设置器

    def of_height(self, height):
        self.height = height
        return self

    def with_name(self, name):
        self.name = name
        return self

    ...

目标是从项目中的几个地方调用它,如下所示:

q = Query()
q.of_height(175).with_name("Alice")

然后我想调用一个q.validate()来检查是否设置任何字段,然后再使用此查询调用 API。

我想不出一种方法来动态检查所有可能的变量,无论是否设置,以检查是否有任何未设置。 理想情况下,我不想实现每次在此类中添加可能的查询维度时都必须更改的validate

在类主体执行期间收集的变量注释存储在您可以使用的__annotations__属性中。

>>> Query.__annotations__
{'height': int, 'weight': int, 'age': int, 'name': str, 'is_alive': bool}

这记录在“自定义类”部分下的数据模型中。

通常,您不会直接访问此属性,而是使用inspect.get_annotations代替,这提供了一些便利。

在@wim 的解决方案之后,最好从self获取注释,以便validate方法可以与子类一起使用。 以下是使用inspect.get_annotations的实现 - 但请注意,它是 3.10 功能。

#!/usr/bin/env python3.10

import inspect
import itertools

class Query:
    height: int
    weight: int
    age: int
    name: str
    is_alive: bool = True

class Query2(Query):
    foo: int

    def get_annotated_attrs(self):
        return set(itertools.chain.from_iterable(inspect.get_annotations(Q).keys() for Q in self.__class__.__mro__))

    def validate(self):
        for name in self.get_annotated_attrs():
            if not hasattr(self, name):
                return False
        return True

q2 = Query2()
print(q2.get_annotated_attrs())
print(q2.validate())

我在想这样的事情

import inspect

class Query:
    height: int
    weight: int
    age: int
    name: str
    is_alive: bool = True
    
    avilable_dimentions = ['height', 'weight', 'age', 'name', 'is_alive']

    def of_height(self, height):
        self.height = height
        return self

    def with_name(self, name):
        self.name = name
        return self
    
    def validate(self):
        not_defined = []
        for dim in self.avilable_dimentions:
            try:
                eval(f'self.{dim}')
            except:
                not_defined.append(dim)
        
        if not_defined:
            raise Exception(f'Missing dimentions {not_defined}') 
        return self

class Query2(Query):
    height2: int
    weight2: int

    avilable_dimentions = Query.avilable_dimentions + ['height2', 'weight2']
    

q = Query2()
q = q.of_height(175).with_name("Alice").validate()

暂无
暂无

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

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