首页 > 解决方案 > Python 获取类中的@property.setter 修饰方法

问题描述

在 Python 中没有 switch/case。建议使用字典:case/switch 语句的 Python 等价物是什么?

@property在 Python 中,使用实现 getter/setter是一种很好的做法:使用 getter 和 setter 的 Python 方式是什么?

因此,如果我想构建一个具有要切换的属性列表的类,以便我可以获取或更新值,我可以使用类似的东西:

class Obj():                                                                                          
"""property demo"""                                                                                  

    @property                                                                                
    def uno(self):                                                                                              
        return self._uno                                                                                       
    @uno.setter                                                                                
    def uno(self, val):                                                                            
        self._uno = val*10                                                                                   

    @property                                                                                          
    def options(self):                                                                                        
        return dict(vars(self))   

但是打电话

o=Obj()
o.uno=10 # o.uno is now 100
o.options

我得到 {'_uno': 100}而不是{'uno': 100}。我错过了什么吗?

标签: python-3.xclasspropertiesswitch-statementdecorator

解决方案


vars确实是一种自省工具,它为您提供当前空间或给定对象中的局部变量 - 这不是获取属性和变量以供最终使用的好方法。

因此,您的options代码必须更复杂一些 - 一种方法是在类中搜索任何属性,然后使用getattr来获取这些属性的值,但使用getter代码并内省实例变量来获取任何方法直接归因,但丢弃以 开头的那些_


    @property                                                                                          
    def options(self):            
        results = {}
        # search in all class attributes for properties, including superclasses:
        for name in dir(self.__class__):
            # obtain the object taht is associated with this name in the class
            attr = getattr(self.__class__, name)
            if isinstance(attr, property):   
                # ^ if you want to also retrieve other "property like"
                # attributes, it is better to check if it as the `__get__` method and is not callable:
                # "if hasattr(attr, '__get__') and not callable(attr):"

                # retrieves the attribute - ensuring the getter code is run:
                value = getattr(self, name)
                results[name] = value
        # check for the attributes assigned directly to the instance:
        for name, value in self.__dict__.items():
            # ^ here, vars(self) could have been used instead of self.__dict__ 
            if not name.startswith("_"):
                results[name] = value

        return results   

关于 switch..case

在您的问题的旁注中,关于“switch...case”构造:请忽略您读到的所有内容,即“在 Python 中应该使用字典而不是 switch/case”。这是不正确的。

在 Python 中替换“switch...case”的正确结构是“if..elif..else”。在 Python 中,你可以使用类似 C 的“switch”和一个普通的“if-else”树来拥有所有表现力,实际上,远不止于此,因为其中的测试表达式if...elif可以是任意的,而不仅仅是一个匹配值。

option = get_some_user_option()
if option == "A":
   ...
elif option == "B":
   ...
elif option in ("C", "D", "E"):
   # common code for C, D, E
   ...
   if option == "E":
        # specialized code for "E",  
else:
   # option does not exist.
   ...

虽然可以将字典用作调用表,并具有在字典值中执行操作的函数,但这种构造显然不是普通 switch 案例的“直接”替代品——从“案例”的点开始函数不能在字典中内联编写,除非它们可以编写为 lambda 函数,主要是因为它们无法直接访问调用它们的函数上的变量。


推荐阅读