18

我想调用一个方法来给我所有“非私有”(我在这里使用术语“私有”有点松散,因为它在 Python 中并不真正存在)和非内置属性(即那些不要以单下划线或双下划线开头)。类似 vars(MyClass) 的东西只会返回该类的“公共”属性。

我知道

from M import * 

不导入名称以下划线开头的对象。(http://www.python.org/dev/peps/pep-0008/#id25) import 是如何实现的?通过内置函数还是仅通过检查下划线?这样做的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方式来做到这一点。

有关下划线和双下划线的更多信息,请参阅: 对象名称前的单下划线和双下划线是什么意思?

4

3 回答 3

13

使用过滤 vars() 的字典理解

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

移动到一个函数中,该函数返回不是“软私有”或可调用的属性列表。如果您愿意,可以通过更改为上面的dict理解来返回值

def list_public_attributes(input_var):
    return [k for k, v in vars(input_var).items() if
            not (k.startswith('_') or callable(v))]
于 2015-07-26T18:48:12.630 回答
2

实际上,存在这样的函数是不合 Python 的——因为“官方”在 Python 中没有私有或受保护的字段/属性。

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

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


*“在import *某个模块期间”

通常这不是最佳做法。考虑下一个例子:

模块Aa1a2定义

模块Bb1b2定义

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

from A import a1, a2
from B import *

a1想象一下我们在 module 中添加函数B。现在突然模块C坏了,虽然我们还没有碰过它。

于 2013-06-12T21:01:16.940 回答
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)))

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

于 2015-06-29T09:10:36.463 回答