Is there a Python method to access all non-private and non-builtin attributes of a class?

自作多情 提交于 2021-02-06 20:01:25

问题


I would like to call a method to give me a dict of all of the "non-private" (I use the term "private" somewhat loosely here since it does not really exist in Python) and non-builtin attributes (i.e. those that do not begin with a single or double underscore) on a class. Something like vars(MyClass) that would return only the "public" attributes on that class.

I'm aware that

from M import * 

does not import objects whose name starts with an underscore. (http://www.python.org/dev/peps/pep-0008/#id25) How does import implement that? Via a builtin function or just by checking for underscores? What is the pythonic way to do this?

Example:

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'

If I do

vars(MyClass).keys()

I get

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

How can I get only

['public']

Or do I just need to check for underscores myself? It just seems like there would be a pythonic way to do this.

For more on underscores and double underscores, see: What is the meaning of a single- and a double-underscore before an object name?


回答1:


With a dict comprehension that filters vars()

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

Moved into a function that returns a list of attributes that are not 'soft private' or callables. You can return values if you like by changing to dict comprehension as above

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



回答2:


Actually, it would be unpythonic for such function to exists - because "officially" there is no private or protected fields/properties in Python.

While it makes sense to throw away module attributes with leading underscores (which are usually some implementation details) during import * from some module*, it is not useful in context of any other object.

So, if you need to list only "public" methods/attributes of an object, just iterate through result of dir and drop names with leading underscores.


* "during import * from some module'"

Usually it is not the best practice. Consider the next example:

module A has a1 and a2 defined

module B has b1 and b2 defined

This code in module C works as expected:

from A import a1, a2
from B import *

Imagine we add function a1 in module B. Now suddenly module C is broken, although we haven't touched it.




回答3:


I'm using this function:

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

I know it's not exactly what you want, but maybe it'll give you some idea.



来源:https://stackoverflow.com/questions/17075071/is-there-a-python-method-to-access-all-non-private-and-non-builtin-attributes-of

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!