How to get attributes (not methods) of a class in Python - python-3.x

How to get attributes (not methods) of a class in Python
Hello everyone!
Basically, I'm looking to retrieve all attributes of a class without having access to self (To create a diagram that includes the attributes).
For now I don't have any code, I just have an 'obj' variable which contains the class.
I would therefore like to know, how, via "obj" I can retrieve all the attributes including those which are in functions.
Thanking you in advance,
VitriSnake

You can call __dict__ on your class and it will return a dictionary containing all attributes with their values set by the constructor.
class Tree:
def __init__(self):
self.trunk_size = 20
self.leaf_colour = "Orange"
if "__main__" == __name__:
tree = Tree()
print(tree.__dict__)
Result: {'trunk_size': 20, 'leaf_colour': 'Orange'}
If you just want the values call tree.__dict__.values() and for your keys or rather attribute variable names do tree.__dict__.keys().

Related

Sphinx: Share function Docstring [duplicate]

I have a class like this:
class MyBase(object):
x = 3
"""Documentation for property x"""
and another class that inherits it:
class MyObj(MyBase):
x = 0
When I use sphinx's autodoc to generate documentation, MyObj.x is not documented. Is there any way to inherit the docstring from MyBase.x? I found DocInherit but since this uses a decorator, it only works for class methods. Any way to do this with properties?
I found a workaround using the property function:
class MyBase(object):
_x = 3
x = property( lambda s: s._x, doc="Documentation for property x")
class MyObj(MyBase):
_x = 0
This is nice in that given an instance variable:
>>> m = MyObj()
>>> m.x
0
one can call help(m) and get proper documentation of property x and sphinx also picks this up correctly.
As far as I know, docstrings for attributes are not part of Python. When I try it, MyBase.x.__doc__ does not get set to the string beneath it. Docstrings only work on classes, functions and methods. If Sphinx picks up the string underneath x = 3 as a docstring, it's probably doing its own processing of the source code to get that.
If you only care for building Documentation via Sphinx. you can use:
":inherited-members:"
.. autoclass:: Noodle
:members:
:inherited-members:
This will also add the doc strings of inherited members in Sphinx Documentation.
http://sphinx-doc.org/ext/autodoc.html
As Thomas already stated, attributes do not have docstrings in Python. Sphinx however provides it's own processing allowing for attributes to be documented.
class Test(object):
#: This is an attibute docstring.
test_attr = 'test'
#property
def test_prop(self):
"""This is a property docstring."""
This results in:
class Test
Bases: object
test_attr = 'test'
This is an attibute docstring.
test_prop
This is a property docstring.

Can anyone explain me about __init_ in Python?

List item
class Car:
def __init__(self, color, brand, number_of_seats):
self.color = color
self.brand = brand
self.number_of_seats = number_of_seats
self.number_of_wheels = 4
self.registration_number = GenerateRegistrationNumber()
Hi all,
1)Referring to the above example, could anyone tell me what is the difference between specific attributed and "the other" attributes? What will happen if registration_number is treated as a specific attribute?
2)
class MyInteger:
def __init__(self, newvalue):
# imagine self as an index card.
# under the heading of "value", we will write
# the contents of the variable newvalue.
self.value = newvalue
If we consider this example, shouldn't it be self.newvalue = newvalue?
I think I know what you're asking (let me know if I'm wrong), but I think you're asking what the difference is between the attributes that are assigned by the parameters of __init__ (Instance Attributes), ones that are assigned inside the __init__ method but not with parameters (also Instance Attributes), and ones that are not assigned in the initialiser at all (Class Attributes). The difference here is that all (well, pretty much all) cars have 4 wheels, and the number plate is generated, not supplied. You could also do this, for example:
class Car:
number_of_wheels = 4
def __init__(self, color, brand, number_of_seats):
self.color = color
self.brand = brand
self.number_of_seats = number_of_seats
self.registration_number = GenerateRegistrationNumber()
As the number of wheels here is always assigned to the same value, across all instances, it is said to be a "Class Attribute" in this case. All other attributes here are “Instance Attributes” as they are specifically assigned to each instance. For a slightly better explanation, I recommend reading this:
https://www.geeksforgeeks.org/class-instance-attributes-python/
It doesn't actually matter what the instance attribute (self.value here) is called, you could call it whatever you want and it'd still work, but in most cases, you would indeed want to name the attribute the same as the parameter.
init function also called as magic function is a constructor function for a class. if you remember in java whenever we make a class the constructor method should have the same name as the classname but this is not the scenario in python . In python we make use of the init method
the difference between the class attributes and instance attributes is that the class attributes are common to every object that is created but the instance attributes are only accessible by the object that is created.
consider a example where data of students in a class is stored. In such case the class division will be same for all the students of that particular class so it can be common but names of all students are different and also their marks and so on and hence they should be different for everyone
in previous scenario the class division can be class attribute and the data of student like name , marks has to be instance attributes
examples of class attribute is as shown
class A:
Division = 5A
here the division is a class attribute
class B:
def __init__(self,name,marks):
self.name = name
self.marks = marks
here the name and marks are instance variables
now here we can also write self.username = name because we are storing the value of name variable in self.username so you can write any name there is no constraint on that
Also whenever you write __ in front of method or variable it means that the attribute is private and accessible by only class.

python property referring to property/attribute of member attribute?

I'm wondering if I have:
class A(object):
def __init__(self):
self.attribute = 1
self._member = 2
def _get_member(self):
return self._member
def _set_member(self, member):
self._member = member
member = property(_get_member, _set_member)
class B(object):
def __init__(self):
self._member = A()
def _get_a_member(self):
return self._member.member
def _set_a_member(self, member):
self._member.member = member
member = property(_get_a_member, _set_a_member)
Can I somehow avoid to write get/setters for A.member, and simply refer to the attribute or property of the A object?
Where the get/setters do logic, its of course needed, but if I simply wan't to expose the member/attributes of a member attribute, then writing get/setters seems like overhead.
I think even if I could write the get/setters inline that would help?
I find the question a bit unclear, however I try to explain some context.
Where the get/setters do logic, its of course needed, but if I simply wan't to expose the member/attributes of a member attribute
If there is no logic in getter/setters, then there is no need to define the attribute as a property, but the attribute can be used directly (in any context).
So
class A(object):
def __init__(self):
self.attribute = 1
self.member = 2
class B(object):
def __init__(self):
self.member = A()
B().member.member # returns 2
B().member.member = 10
In some languages, it's considered good practice to abstract instance properties with getter/setter methods, That's not necessarily the case in Python.
Python properties are useful when you'd need more control over the attribute, for example:
when there is logic (validation, etc.)
to define a readonly attribute (so only providing a getter without a setter)
Update (after the comment)
properties are not necessarily a tool to "hide" some internal implementation. Hiding in Python is a bit different than say in Java, due to very dynamic nature of Python language. It's always possible to introspect and even change objects on the fly, you can add new attributes (even methods) to objects on runtime:
b = B()
b.foo = 4 # define a new attribute on runtime
b.foo # returns 4
So Python developers rely more on conventions to hint their intentions of abstractions.
About the polymorphic members, I think it's most natural for Python classes to just share an interface, that's what's meant by Duck typing. So as long as your next implementation of A supports the same interface (provides the same methods for callers), it should not be any issue to change its implementation.
So this is what I came up with - use a method to generate the properties, with the assumption that the obj has an attribute of _member:
def generate_cls_a_property(name):
"""Small helper method for generating a 'dumb' property for the A object"""
def getter(obj):
return getattr(obj._member, name)
def setter(obj, new_value):
setattr(obj._member, name, new_value)
return property(getter, setter)
This allows me to add properties like so:
class B(object):
def __init__(self):
self._member = A()
member = generate_cls_a_property('member') # generates a dumb/pass-through property
I'll accept my own, unless someone tops it within a week.. :)

Create instances from list of classes

How do I create instances of classes from a list of classes? I've looked at other SO answers but did understand them.
I have a list of classes:
list_of_classes = [Class1, Class2]
Now I want to create instances of those classes, where the variable name storing the class is the name of the class. I have tried:
for cls in list_of_classes:
str(cls) = cls()
but get the error: "SyntaxError: can't assign to function call". Which is of course obvious, but I don't know what to do else.
I really want to be able to access the class by name later on. Let's say we store all the instance in a dict and that one of the classes are called ClassA, then I would like to be able to access the instance by dict['ClassA'] later on. Is that possible? Is there a better way?
You say that you want "the variable name storing the class [to be] the name of the class", but that's a very bad idea. Variable names are not data. The names are for programmers to use, so there's seldom a good reason to generate them using code.
Instead, you should probably populate a list of instances, or if you are sure that you want to index by class name, use a dictionary mapping names to instances.
I suggest something like:
list_of_instances = [cls() for cls in list_of_classes]
Or this:
class_name_to_instance_mapping = {cls.__name__: cls() for cls in list_of_classes}
One of the rare cases where it can sometimes make sense to automatically generate variables is when you're writing code to create or manipulate class objects themselves (e.g. producing methods automatically). This is somewhat easier and less fraught than creating global variables, since at least the programmatically produced names will be contained within the class namespace rather than polluting the global namespace.
The collections.NamedTuple class factory from the standard library, for example, creates tuple subclasses on demand, with special descriptors as attributes that allow the tuple's values to be accessed by name. Here's a very crude example of how you could do something vaguely similar yourself, using getattr and setattr to manipulate attributes on the fly:
def my_named_tuple(attribute_names):
class Tup:
def __init__(self, *args):
if len(args) != len(attribute_names):
raise ValueError("Wrong number of arguments")
for name, value in zip(attribute_names, args):
setattr(self, name, value) # this programmatically sets attributes by name!
def __iter__(self):
for name in attribute_names:
yield getattr(self, name) # you can look up attributes by name too
def __getitem__(self, index):
name = attribute_names[index]
if isinstance(index, slice):
return tuple(getattr(self, n) for n in name)
return getattr(self, name)
return Tup
It works like this:
>>> T = my_named_tuple(['foo', 'bar'])
>>> i = T(1, 2)
>>> i.foo
1
>>> i.bar
2
If i did understood your question correctly, i think you can do something like this using globals():
class A:
pass
class B:
pass
class C:
pass
def create_new_instances(classes):
for cls in classes:
name = '{}__'.format(cls.__name__)
obj = cls()
obj.__class__.__name__ = name
globals()[name] = obj
if __name__ == '__main__':
classes = [A, B, C]
create_new_instances(classes)
classes_new = [globals()[k] for k in globals() if k.endswith('__') and not k.startswith('__')]
for cls in classes_new:
print(cls.__class__.__name__, repr(cls))
Output (you'll get a similar ouput):
A__ <__main__.A object at 0x7f7fac6905c0>
C__ <__main__.C object at 0x7f7fac6906a0>
B__ <__main__.B object at 0x7f7fac690630>

Preventing a particular attribute's inheritance in subclass?

If I have the following :
class A:
attrs = [...]
A_attr = [...]
class B(A):
B_attr = [...]
Is there a way to prevent my B subclass from inheriting the A_attr from the A class?
Or would this be considered a bad design and I should better subclass both A and B from a third C class containing all the attrs attributes and add the particular attribute to each subclass like this?
class C:
attrs = [...]
class A(C):
A_attr = [...]
class B(C):
B_attr = [...]
Better idea is to dump the common functionality in a class.
class Commmon:
attrs = [...]
Extend this class who want this extra functonality.
class A(Common):
# only one attribute added in this class
A_attr = [...]
classB(Common):
attrs_B = [...]
Extend class A when that extra attribute is needed in the class, this will bring all those other attributes.
class C(A):
attrs_C = [...]
What this will allow is wherever you want an object of type Common you can provide instance of B as well as C. And wherever you want instance of class A you can provide instance of C. If you add specific instance in each of your subclasses you will not be able to do so.
From Comment
So according to you I should use the second solution I exposed in my question.
No.
Instead of adding the attribute in each subclass, my advice is to add the attribute in a separate class and let your new classes inherit this intermediate class. So you do not have to add the specific attribute in each one of those subclass.
Example is already provided above. Lets see what is the benefit of doing this, as opposed to your suggestion. Take the following function
def foo(obj):
# check to make sure object has the specific attribute
if (isinstance(obj, A)):
pass; #do something
else:
raise TypeError("Object is not an instance of A")
But if we add the specific attribute in each class, the method will need to be changed to something like this:
def foo(obj):
# check to make sure object has the those type which has that specific attribute
if( isinstance(obj, class1) or (isinstance(obj, class2) or ...):
pass; #do something
else:
raise TypeError("Object does not have specific attribute")
Of course, you can perform a check using something like this:
def foo(obj):
# check to make sure obj has attribute
if hasattr(obj, 'property')
pass; # do something
else:
raise TypeError("Object does not have necessary attribute")
Using correct inheritance relationship (as shown in 1st example) will also help your IDE (if you are using one) in inferring types, because IDE can determine which type of object it expects. You can even augment the function with type information like this:
def foo(obj : A):
pass; #do something
That A after colon is a hint to the IDE that function expects an object of type or subtype of A.

Resources