首页 文章

是否有Python方法可以访问类的所有非私有和非内置属性?

提问于
浏览
6

我想调用一种方法给我一个所有“非私有”的词典(我在这里使用“私有”一词,因为它在Python中并不存在)和非内置属性(即那些在类上不要以单个或双下划线开头 . 像vars(MyClass)这样的东西只能返回该类的“公共”属性 .

我知道

from M import *

不会导入名称以下划线开头的对象 . (http://www.python.org/dev/peps/pep-0008/#id25)导入如何实现?通过内置函数或仅通过检查下划线?什么是pythonic方法呢?

例:

class MyClass(object):
    def __init__(self):
        do_stuff()
    def _private(self):
        print 'private'
    def __gets_name_mangled(self:
        print 'becomes _MyClass__gets_name_mangled()'
    def public(self):
        print 'public'

如果我做

vars(MyClass).keys()

我明白了

['_MyClass__gets_name_mangled', '__module__', '_private', '__doc__', '__dict__', '__weakref__', 'public', '__init__']

我怎么才能得到

['public']

或者我只是需要自己检查下划线?看起来似乎会有一种pythonic方式来做到这一点 .

有关下划线和双下划线的更多信息,请参阅:What is the meaning of a single- and a double-underscore before an object name?

3 回答

  • 3

    实际上,存在这样的函数将是unpythonic - 因为“正式”Python中没有私有或受保护的字段/属性 .

    虽然在某些模块*的 import * 期间丢弃具有前导下划线的模块属性(通常是一些实现细节)是有意义的,但它在任何其他对象的上下文中都没有用 .

    因此,如果您只需要列出对象的"public"方法/属性,只需遍历 dir 的结果并删除带有前导下划线的名称 .


    *“来自某个模块的 import *

    通常这不是最好的做法 . 考虑下一个例子:

    模块 A 已定义 a1a2

    模块 B 已定义 b1b2

    模块_1783595中的此代码按预期工作:

    from A import a1, a2
    from B import *
    

    想象一下,我们在模块 B 中添加函数 a1 . 现在突然模块 C 被破坏了,虽然我们没有触及它 .

  • 4

    使用dict理解过滤vars()

    { k:v for k,v in vars(myObject).items() if not k.startswith('_') }
    

    移动到一个函数,该函数返回非“软私有”或可调用的属性列表 . 如果您愿意,可以通过更改为上述字典理解来返回值

    def list_public_attributes(input_var):
        return [k for k, v in vars(input_var).items() if
                not (k.startswith('_') or callable(v))]
    
  • 1

    我正在使用这个功能:

    def print_all_public_fields(obj):
        print(obj)
        for a in dir(obj):
            if not a.startswith('_') and not a.isupper():
                print('\t%s = %s' % (a, getattr(obj, a)))
    

    我知道这不是你想要的,但也许它会给你一些想法 .

相关问题