Try the inspect module. getmembers and the various tests should be helpful.

EDIT:

For example,

class MyClass(object):
    a = '12'
    b = '34'
    def myfunc(self):
        return self.a

>>> import inspect
>>> inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a)))
[('__class__', type),
 ('__dict__',
  <dictproxy {'__dict__': <attribute '__dict__' of 'MyClass' objects>,
   '__doc__': None,
   '__module__': '__main__',
   '__weakref__': <attribute '__weakref__' of 'MyClass' objects>,
   'a': '34',
   'b': '12',
   'myfunc': <function __main__.myfunc>}>),
 ('__doc__', None),
 ('__module__', '__main__'),
 ('__weakref__', <attribute '__weakref__' of 'MyClass' objects>),
 ('a', '34'),
 ('b', '12')]

Now, the special methods and attributes get on my nerves- those can be dealt with in a number of ways, the easiest of which is just to filter based on name.

>>> attributes = inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a)))
>>> [a for a in attributes if not(a[0].startswith('__') and a[0].endswith('__'))]
[('a', '34'), ('b', '12')]

...and the more complicated of which can include special attribute name checks or even metaclasses ;)

Answer from Matt Luongo on Stack Overflow
🌐
GeeksforGeeks
geeksforgeeks.org › python › python-attributes-class-vs-instance-explained
Python Attributes: Class Vs. Instance Explained - GeeksforGeeks
July 23, 2025 - In Python, attributes are properties associated with objects. They can be variables or methods that are defined within a class or an instance of a class. Understanding the difference between class and instance attributes is fundamental in ...
🌐
Built In
builtin.com › software-engineering-perspectives › python-attributes
Python Attributes: Class vs. Instance | Built In
Python attributes are variables or methods associated with an object that store data about the object's properties and behavior. Class attributes belong to a class, while instance attributes belong to a specific object and are unique to each object.
Discussions

python - Getting attributes of a class - Stack Overflow
I want to get the attributes of a class, say: class MyClass(): a = "12" b = "34" def myfunc(self): return self.a using MyClass.__dict__ gives me a list of attributes and functions, and ... More on stackoverflow.com
🌐 stackoverflow.com
Python function attributes - uses and abuses - Stack Overflow
Not many are aware of this feature, but Python's functions (and methods) can have attributes. Behold: >>> def foo(x): ... pass ... >>> foo.score = 10 >>> dir(fo... More on stackoverflow.com
🌐 stackoverflow.com
class - Difference between methods and attributes in python - Stack Overflow
I am learning python and doing an exercise about classes. It tells me to add an attribute to my class and a method to my class. I always thought these were the same thing until I read the exercise.... More on stackoverflow.com
🌐 stackoverflow.com
What is the difference in python attributes with underscore in front and back - Stack Overflow
I want to know what is the difference between these in Python? self._var1 self._var1_ self.__var1 self.__var1__ More on stackoverflow.com
🌐 stackoverflow.com
🌐
Real Python
realpython.com › ref › glossary › attribute
attribute | Python Glossary – Real Python
In Python, an attribute is a value associated with an object that can be accessed using dot notation (object.attribute).
🌐
Python documentation
docs.python.org › 3 › tutorial › classes.html
9. Classes — Python 3.14.3 documentation
Each class instance can have attributes attached to it for maintaining its state. Class instances can also have methods (defined by its class) for modifying its state. Compared with other programming languages, Python’s class mechanism adds classes with a minimum of new syntax and semantics.
🌐
Tutorialspoint
tutorialspoint.com › python › python_class_attributes.htm
Python - Class Attributes
The properties or variables defined inside a class are called as Attributes. An attribute provides information about the type of data a class contains. There are two types of attributes in Python namely instance attribute and class attribute.
🌐
Alma Better
almabetter.com › bytes › tutorials › python › methods-and-attributes-in-python
Attributes and Methods in Python
February 29, 2024 - Attributes in Python are variables that belong to an object and contain information about its properties and characteristics. They can be used to represent details or facts related to the object.
Find elsewhere
🌐
Python documentation
docs.python.org › 3 › reference › datamodel.html
3. Data model — Python 3.14.3 documentation
Future versions of Python may add types to the type hierarchy (e.g., rational numbers, efficiently stored arrays of integers, etc.), although such additions will often be provided via the standard library instead. Some of the type descriptions below contain a paragraph listing ‘special attributes.’ These are attributes that provide access to the implementation and are not intended for general use.
🌐
freeCodeCamp
freecodecamp.org › news › python-attributes-class-and-instance-attribute-examples
Python Attributes – Class and Instance Attribute Examples
April 12, 2022 - When creating a class in Python, you'll usually create attributes that may be shared across every object of a class or attributes that will be unique to each object of the class. In this article, we'll see the difference between class attributes and ...
🌐
Bruceeckel
bruceeckel.com › 2022 › 05 › 11 › misunderstanding-python-class-attributes
Misunderstanding Python Class Attributes
May 11, 2022 - In class B, x is changed to a static variable, which means there is only a single piece of x storage for the class—no matter how many instances of that class you create. This is how Python class attributes work; they are static variables without using the static keyword.
🌐
YouTube
youtube.com › watch
What Is A Class Attribute In Python - YouTube
In this python tutorial, we are talking about classes and I answer the question of what is a class attribute in python! I show you a couple of examples of cl...
Published   February 24, 2023
🌐
Python documentation
docs.python.org › 3 › tutorial › datastructures.html
5. Data Structures — Python 3.14.3 documentation
Though tuples may seem similar to lists, they are often used in different situations and for different purposes. Tuples are immutable, and usually contain a heterogeneous sequence of elements that are accessed via unpacking (see later in this section) or indexing (or even by attribute in the ...
Top answer
1 of 1
103

As a starting point, you will probably find helpful this quote from PEP 8 - Style Guide For Python Code:

In addition, the following special forms using leading or trailing underscores are recognized (these can generally be combined with any case convention):

_single_leading_underscore: weak "internal use" indicator. E.g. from M import * does not import objects whose name starts with an underscore.

single_trailing_underscore_: used by convention to avoid conflicts with Python keyword, e.g. Tkinter.Toplevel(master, class_='ClassName')

__double_leading_underscore: when naming a class attribute, invokes name mangling (inside class FooBar, __boo becomes _FooBar__boo; see below).

__double_leading_and_trailing_underscore__: "magic" objects or attributes that live in user-controlled namespaces. E.g. __init__, __import__ or __file__. Never invent such names; only use them as documented.

You asked in the context of class attributes, though, so let's take a look at your specific examples:

Single leading underscore

Naming an attribute in your class self._var1 indicates to the user of the class that the attribute should only be accessed by the class's internals (or perhaps those of a subclass) and that they need not directly access it and probably shouldn't modify it. You should use leading underscores in the same places that you would use a private or protected field in Java or C#, but be aware that the language doesn't actually enforce non-access - instead you trust your class's user to not do anything stupid, and leave them the option of accessing (or modifying) your class's private field if they're really, really sure that they know what they're doing and it makes sense.

Single leading and trailing underscore

self._var1_ isn't something I've ever seen. I don't think this naming style has any conventional meaning in the Python world.

Double leading underscore

This one actually has syntactical significance. Referring to self.__var1 from within the scope of your class invokes name mangling. From outside your class, the variable will appear to be at self._YourClassName__var1 instead of self.__var1. Not everyone uses this - we don't at all where I work - and for simple classes it feels like a slightly absurd and irritating alternative to using a single leading underscore.

However, there is a justification for it existing; if you're using lots of inheritance, if you only use single leading underscores then you don't have a way of indicating to somebody reading your code the difference between 'private' and 'protected' variables - ones that aren't even meant to be accessed by subclasses, and ones that subclasses may access but that the outside world may not. Using a single leading underscore to mean 'protected' and a double underscore to mean 'private' may therefore be a useful convention in this situation (and the name mangling will allow a subclasses to use a variable with the same name in their subclass without causing a collision).

Double leading and trailing underscore

self.__var1__ is something you should never create as I've literally written it, because the double leading and trailing underscore naming style is meant to be used only for names that have a special meaning defined by Python, like the __init__ or __eq__ methods of classes. You're free to override those to change your class's behavior (indeed, almost all classes will have a programmer-defined __init__), but you shouldn't make up your own names in this style like self.__var1__.

🌐
Reddit
reddit.com › r/learnpython › why use underscore class attributes?
r/learnpython on Reddit: Why use underscore class attributes?
June 14, 2022 -

Recently I more than once stumbled upon code where classes where defined such that they were initialized with an underscore attribute. These classes then also contain a property to return that attribute without an underscore. See this example:

    class Character(object): 
     """ Defines the character class """ 
  
     def __init__(self, name): 
         """ Initialize the class """ 
         self._name = name 
  
     @property 
     def name(self): 
         """ Name of the character """ 
         return self._name 

What is the advantage over just initializing it with self.name instead of self._name?

🌐
Python Morsels
pythonmorsels.com › python-setattr
Python's setattr function and __setattr__ method - Python Morsels
June 9, 2022 - Python's built-in setattr function can dynamically set attributes given an object, a string representing an attribute name, and a value to assign.
🌐
Real Python
realpython.com › python-dict-attribute
Using Python's .__dict__ to Work With Attributes – Real Python
March 12, 2025 - The .__dict__ attribute is fundamental to Python’s data model. The interpreter recognizes and uses it internally to process classes and objects. It enables dynamic attribute access, addition, removal, and manipulation. You’ll learn how to do these operations in a moment.
Top answer
1 of 3
4

TLDR: The attribute is the value produced by looking up the attribute name.


According to the Python Language Reference, Attribute references, in the statement

value = obj.name

obj.name is an attribute reference, name is the attribute name, and the produced value is the attribute. Note that value is the attribute in this case because it was produced by the attribute reference, not because it is inherently related. For example, an attribute reference may produce a new value every time it is evaluated.

The primary must evaluate to an object of a type that supports attribute references, which most objects do. This object is then asked to produce the attribute whose name is the identifier. This production can be customized by overriding the __getattr__() method. If this attribute is not available, the exception AttributeError is raised. Otherwise, the type and value of the object produced is determined by the object. Multiple evaluations of the same attribute reference may yield different objects.

In an attribute assignment such as

obj.name = value

the value does not necessarily become the attribute. If the attribute name points to a data descriptor, value may be stored, modified or discarded.

2 of 3
1

First let's talk about general objects in Python. The documentation defines 3 characteristics for every object:

  • identity

    An object’s identity never changes once it has been created; you may think of it as the object’s address in memory.

  • type

    An object’s type determines the operations that the object supports (e.g., “does it have a length?”) and also defines the possible values for objects of that type. The type() function returns an object’s type (which is an object itself). Like its identity, an object’s type is also unchangeable.

  • value

    The value of some objects can change. Objects whose value can change are said to be mutable; objects whose value is unchangeable once they are created are called immutable.

Understanding objects means understanding types, but types are objects also. These TypeObjects are one of the most important structures in Python and define the basic functionality of an object. Specifically they implement the getattr and setattr functions.

The default behavior for this implementation is described here:

The default behavior for attribute access is to get, set, or delete the attribute from an object’s dictionary. For instance, a.x has a lookup chain starting with a.__dict__['x'], then type(a).__dict__['x'], and continuing through the base classes of type(a) excluding metaclasses. If the looked-up value is an object defining one of the descriptor methods, then Python may override the default behavior and invoke the descriptor method instead. [...]

the methods for an class or an instance which can overwrite the default behaviour are __get__, __set__ and __delete__.

The documentation for the __get__ method specifies:

This method should return the computed attribute value or raise an AttributeError exception.

Summarizing all the above, my formal definition for an attribute would be along the lines of:

  • attributes are objects with identity, type and value
  • they are owned by another object

Further reading:

https://docs.python.org/3/reference/datamodel.html

https://docs.python.org/3/c-api/typeobj.html

https://docs.python.org/3/howto/descriptor.html?highlight=descriptor

https://realpython.com/python-descriptors/

🌐
Medium
medium.com › @satishgoda › python-attribute-access-using-getattr-and-getattribute-6401f7425ce6
Python Attribute Access using __getattr__ and __getattribute__ | by Satish Goda | Medium
December 14, 2019 - After studying the official documentation, I wrote the following simple Python class that overrides the base class implementation and injected some print statements followed by calling base class methods. class Yeah(object): def __init__(self, name): self.name = name # Gets called when an attribute is accessed def __getattribute__(self, item): print '__getattribute__ ', item # Calling the super class to avoid recursion return super(Yeah, self).__getattribute__(item) # Gets called when the item is not found via __getattribute__ def __getattr__(self, item): print '__getattr__ ', item return super(Yeah, self).__setattr__(item, 'orphan')