Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 817
andy Avatar asked Jun 12 '13 20:06

andy


People also ask

How do I see all the attributes of an object in Python?

To list all the attributes of an object, use the built-in dir() function. It returns a long list of attribute names, that is, method and variable names of the object.

How do you access the attributes of a class in Python?

Attributes of a class can also be accessed using the following built-in methods and functions : getattr() – This function is used to access the attribute of object. hasattr() – This function is used to check if an attribute exist or not. setattr() – This function is used to set an attribute.

How do you access private attributes in Python?

In Python, there is no existence of Private methods that cannot be accessed except inside a class. However, to define a private method prefix the member name with the double underscore “__”. Note: The __init__ method is a constructor and runs as soon as an object of a class is instantiated.

Which methods can access to private attributes of a class?

Answer: Methods, Variables and Constructors that are declared private can only be accessed within the declared class itself. Private access modifier is more secure and restrictive access level, whereas class and interfaces cannot be private.


3 Answers

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))]
like image 154
kert Avatar answered Sep 27 '22 21:09

kert


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.

like image 33
Roman Bodnarchuk Avatar answered Sep 27 '22 20:09

Roman Bodnarchuk


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.

like image 41
omikron Avatar answered Sep 27 '22 20:09

omikron