I would like to know what is the best way to get all the attributes of a class when I don't know the name of them.
Let's say I have:
#!/usr/bin/python2.4
class A(object):
outerA = "foobar outerA"
def __init__(self):
self.innerA = "foobar innerA"
class B(A):
outerB = "foobar outerB"
def __init__(self):
super(B, self).__init__()
self.innerB = "foobar innerB"
if __name__ == '__main__':
b = B()
Using hasattr/getattr to get the "outerA" class field of my b instance works fine:
>>> print hasattr(b, "outerA")
>>> True
>>> print str(getattr(b, "outerA"))
>>> foobar outerA
Ok, that's good.
But what if I don't exactly know that b has inherited a field called "outerA" but I still want to get it?
To access b's inner fields, I usually use b.__dict__ . To get b.outerB, I can use b.__class__.__dict__ but that still doesn't show "outerA" among it fields:
>>> print "-------"
>>> for key, val in b.__class__.__dict__.iteritems():
... print str(key) + " : " + str(val)
>>> print "-------\n"
Shows:
-------
__module__ : __main__
__doc__ : None
__init__ : <function __init__ at 0xb752aaac>
outerB : foobar outerB
-------
Where's my outerA?? :D
I am sure I can keep "climbing" the class hierarchy and get all the fields, but that doesn't seem like the greatest solution...
As there are hasattr(), getattr()... isn't there something like a listattr() that would give all the available attributes of an instance?
Thank you!
I think you're looking for dir() - it works just as well within code as in the shell.
Try dir(b). The resulting list includes inherited attributes.
Related
How to initialise class as an object with same name
>>> class test:
def name(self,name_):
self.name = name_
>>> a= test()
>>> a
<__main__.test instance at 0x027036C0>
>>> test
<class __main__.test at 0x0271CDC0>
here a is an object so I can do a.name("Hello")
But what I want to achieve is test.name("Hello") without doing something like test = test()
The simple answer is don't bother with a "setter" function. Just access the attribute directly. eg.
a = test()
a.name = "setting an instance attribute"
test.name = "setting the class attribute"
b = test()
# b has no name yet, so it defaults the to class attribute
assert b.name == "setting the class attribute"
If the function is doing something a little more complicated than just setting an attribute then you can make it a classmethod. eg.
class Test(object):
# you are using python 2.x -- make sure your classes inherit from object
# Secondly, it's very good practice to use CamelCase for your class names.
# Note how the class name is highlighted in cyan in this code snippet.
#classmethod
def set_name(cls, name):
cls.name = name
Test.set_name("hello")
assert Test().name == "hello"
I am trying to write call multiple functions through a loop using the getattr(...). Snippet below:
class cl1(module):
I =1
Name= 'name'+str(I)
Func= 'func'+str(I)
Namecall = gettattr(self,name)
Namecall = getattr(self,name)()
This is when get the following code: self.name1 = self.func1()
The desire is to loop multiple of these but the code is not working. Can you please advise?
Firstly, do use CapitalLetters for Classes and lowercase_letters for variables as it is easier to read for other Python programmers :)
Now, you don't need to use getattr() inside the class itself
Just do :
self.attribute
However, an example will be:
class Foo(object): # Class Foo inherits from 'object'
def __init__(self, a, b): # This is the initialize function. Add all arguments here
self.a = a # Setting attributes
self.b = b
def func(self):
print('Hello World!' + str(self.a) + str(self.b))
>>> new_object = Foo(a=1, b=2) # Creating a new 'Foo' object called 'new_object'
>>> getattr(new_object, 'a') # Getting the 'a' attribute from 'new_object'
1
However, an easier way would just be referencing the attribute directly
>>> new_object.a
1
>>> new_object.func()
Hello World!12
Or, by using getattr():
>>> getattr(new_object, 'func')()
Hello World!12
Although I explained the getattr() function,
I don't seem to understand what you want to achieve, do post a sample output.
I have a question regarding python and class initialized variables.
So I recently noticed in Python (2.7.X) that if you set a class variable that hasn't been defined or initialized, you are still able to call and access the data within that variable.
For instance:
class Test:
def __init__(self):
self.a = "Hello"
t = Test()
print t.a
t.b = "World"
print t.b
Output:
Hello
World
I would expect 'print t.b' to error because b hasn't been defined in the Test() class but it runs without any issue. Why is this happening? Can anyone explain?
http://ideone.com/F2LxLh
Thank you for your time.
From the docs on instance objects (t is an instance object because it is an instance of the custom class Test):
Data attributes need not be declared; like local variables, they spring into existence when they are first assigned to.
However you can get your expected behavior by using __slots__ with a new-style class. This overrides the default dictionary storage for attributes to make the object more memory efficient, and it also results in an AttributeError if you try to assign to an attribute not defined in __slots__, for example:
>>> class Test(object):
... __slots__ = ['a']
...
>>> t = Test()
>>> t.a = "Hello"
>>> t.b = "World"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Test' object has no attribute 'b'
This is expected behaviour. You can add attributes in Python at any time without errors. Even without setting attributes in the __init__ you can add new ones on the fly:
>>> class Test:
... pass
...
>>> t = Test()
>>> t.foo = '3'
>>> t.foo
'3'
If you want you can change this behavior by writing your own __setattr__ method ( see docs )
class Test:
def __init__(self):
self.__dict__[ 'a' ] = "Hello"
def __setattr__( self, name, value ):
if name not in self.__dict__:
raise Exception( 'No attribute: ' + name )
else:
self.__dict__[ name ] = value
t = Test()
t.a = 'hello world'
print ( t.a )
t.b = "World" # <<< this will throw exception
Kind of related to this question:
https://stackoverflow.com/questions/8708525/how-to-check-if-mako-function-exist
I want to check if a function exists for a given class, but not inherited, so that the parent can called the child's function, since otherwise it would result in an infinite recursion..
edit:
it actually gives a maximum stack level error, which is the same.
the equivalent code would be:
class A(object):
def f(x):
b = B()
b.f()
class B(A):
pass
a = A()
a.f()
i understand this is not clean or preferred, but it is what the template translates to, and I dunno how to check for it otherwise.
I want to check if a function exists for a given class, but not inherited
Yes, you can check the class dictionary directly. Either use the __dict__ attribute or the built-in vars() function::
>>> class A(object):
def f(x):
pass
>>> class B(A):
def g(x):
pass
>>> 'f' in vars(B)
False
>>> 'g' in vars(B)
True
If what you need is to check whether the method is defined directly in instance's class and not in one of its ancestors then you can try this:
import inspect
def has_method(obj, name):
v = vars(obj.__class__)
# check if name is defined in obj's class and that name is a method
return name in v and inspect.isroutine(v[name])
class A:
def foo(self):
print 'foo'
class B(A):
pass
b = B()
a = A()
print has_method(a, 'foo') # => True
print has_method(b, 'foo') # => False
I want to know how to use variables for objects and function names in Python. In PHP, you can do this:
$className = "MyClass";
$newObject = new $className();
How do you do this sort of thing in Python? Or, am I totally not appreciating some fundamental difference with Python, and if so, what is it?
Assuming that some_module has a class named "class_name":
import some_module
klass = getattr(some_module, "class_name")
some_object = klass()
I should note that you should be careful here: turning strings into code can be dangerous if the string came from the user, so you should keep security in mind in this situation. :)
One other method (assuming that we still are using "class_name"):
class_lookup = { 'class_name' : class_name }
some_object = class_lookup['class_name']() #call the object once we've pulled it out of the dict
The latter method is probably the most secure way of doing this, so it's probably what you should use if at all possible.
In Python,
className = MyClass
newObject = className()
The first line makes the variable className refer to the same thing as MyClass. Then the next line calls the MyClass constructor through the className variable.
As a concrete example:
>>> className = list
>>> newObject = className()
>>> newObject
[]
(In Python, list is the constructor for the list class.)
The difference is that in PHP, you represent the name of the class you want to refer to as a string, while in Python you can reference the same class directly. If you must use a string (for example if the name of the class is created dynamically), then you will need to use other techniques.
If you need to create a dynamic class in Python (i.e. one whose name is a variable) you can use type() which takes 3 params:
name, bases, attrs
>>> class_name = 'MyClass'
>>> klass = type(class_name, (object,), {'msg': 'foobarbaz'})
<class '__main__.MyClass'>
>>> inst = klass()
>>> inst.msg
foobarbaz
Note however, that this does not 'instantiate' the object (i.e. does not call constructors etc. It creates a new(!) class with the same name.
If you have this:
class MyClass:
def __init__(self):
print "MyClass"
Then you usually do this:
>>> x = MyClass()
MyClass
But you could also do this, which is what I think you're asking:
>>> a = "MyClass"
>>> y = eval(a)()
MyClass
But, be very careful about where you get the string that you use "eval()" on -- if it's come from the user, you're essentially creating an enormous security hole.
Update: Using type() as shown in coleifer's answer is far superior to this solution.
I use:
newObject = globals()[className]()
I prefer using dictionary to store the class to string mapping.
>>> class AB:
... def __init__(self, tt):
... print(tt, "from class AB")
...
>>> class BC:
... def __init__(self, tt):
... print(tt, "from class BC")
...
>>> x = { "ab": AB, "bc": BC}
>>> x
{'ab': <class '__main__.AB'>, 'bc': <class '__main__.BC'>}
>>>
>>> x['ab']('hello')
hello from class AB
<__main__.AB object at 0x10dd14b20>
>>> x['bc']('hello')
hello from class BC
<__main__.BC object at 0x10eb33dc0>