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

发布于 2025-02-05 14:02:47 字数 685 浏览 2 评论 0 原文

我正在创建一个类似于查询的类:

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之前,不是设置。

我无法找到一种动态检查所有可能的变量(设置)的方法,以检查是否保持不设置。理想情况下,我不想实现每次在此类中添加可能的查询维度时必须更改的验证

I'm creating a class to represent a query, like this:

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

As you can see, some variables start off initialized with defaults, others don't.

I want to implement chainable setters like so

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

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

    ...

The goal is to call this from several places in the project like so:

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

Then I want to call a q.validate() that checks if any fields were not set, before calling an API with this query.

I can't figure out a way to dynamically check all possible variables, set or not, to check if any were left unset. Ideally, I don't want to implement a validate that has to be changed every time I add a possible query dimension in this class.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

羅雙樹 2025-02-12 14:02:48

变量注释在班级身体执行过程中收集的 代码> __注释__ 您可以使用的属性。

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

这是在

通常,您不会直接访问此属性,而是使用 而不是提供一些便利。

The variable annotations collected during class body execution are stored in an __annotations__ attribute which you can use.

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

This is documented in the datamodel under the "Custom classes" section.

Usually, you would not access this attribute directly but use inspect.get_annotations instead, which provides a few conveniences.

浪推晚风 2025-02-12 14:02:48

在 @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())

Following on @wim's solution, it would be desirable to get annotations from self so that a validate method will work with subclasses. Following is an implementation using inspect.get_annotations - but note that its a 3.10 feature.

#!/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())
只有一腔孤勇 2025-02-12 14:02:48

我在想这样的事情

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()

I was thinking of something like this

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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文