Using getattr function on self in python - python

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.

Related

How can I definine a class inside a function, then access it from outside said function in Python?

Let's assume I have the following code:
#!/usr/bin/python3
def genclass():
class stuff:
foo = 'Foo'
bar = 'Bar'
genclass()
How would I access that class outside of the function? I tried the following:
Just print the function:
print(stuff.foo)
Print it with the function name:
print(genclass.stuff.foo)
Same, but with () to indicate that genclass is a function:
print(genclass().stuff.foo)
Unfortunately, none of the above worked.
One way is you can store the class objects in a list and return the list, but you can only access the classes by index.
def genclass():
class stuff:
foo = 'foo'
bar = 'bar'
class other:
one = 'one'
two = 'two'
return [stuff, other]
>>> genclass()[0].foo
'foo'
>>> genclass()[1].one
'one'
But this is basically treating the function as a list.
edit::
You can also use it as both a function that executes another command if you include an if-statement to check if a parameter is passed.
def genclass(arg = None):
class stuff:
foo = 'foo'
bar = 'bar'
if arg:
print('parameter passed')
else:
return [stuff]
>>> genclass()[0].bar
'bar'
>>> genclass(1)
parameter passed
What you want to do is setting an attribute in a function. You can't do it directly, but you need to call the setattr function.
You can do something like:
def genclass():
class stuff:
foo = 'Foo'
bar = 'Bar'
setattr(genclass, 'stuff', stuff)
And then, after executing the function, because everything inside a function is ran just after its execution, you can access the class by typing
genclass.stuff
Anyway, this is a workaround and I don't think it is a best practice.
For better understand what a function is in Python and why you can set them an attribute please have a look on https://www.tutorialspoint.com/What-are-Python-function-attributes

Calling a variable from a classmethod function to a normal method

I would like to call a variable from a classmethod to a different method inside the same class:
class A():
#classmethod
def b(cls):
cls.g = 5
def c(self):
if self.g < 1:
print("TestA")
else:
print("TestB")
When doing:
x = A()
x.c()
I get:
AttributeError: 'A' object has no attribute 'g'
I've read and searched for a similar case but haven't found one. Most deal with calling variables from the init method and that doesn't apply here.
If you don't run .b() beforehand, your .g doesn't exist,...at all.
Add an __init__ function to your class and declare .g there to make sure it exists at least.
You did not define g as a class attribute of the class A. This could be done this way:
class A():
g = 7
but then in your code you are treating g as instance (self.g) and class variable (cls.g) at the same time. While this works (self.g will refer to cls.g) it may be confusing.

Create an object of the same class within the class

I want to have an object of a class within a class, because I need to pass it to a method, similarly to the example below. I would like the example below to print out 1, or fooObj.fooNum, but I keep getting a NameError: name 'foo' is not defined.
class bar:
def fooDef(self, fooObj):
print fooObj.fooNum
class foo:
fooNum = 1
b = bar()
f = foo()
b.fooDef(f)
Please, can you be more specific about what you are trying to do?
The error you see is normal, because the code immediately below class foo will be executed during the definition of foo and therefore the class is not defined yet.
If I understand well you want to define some method foobar of the class foo, which will use a foo instance. The correct procedure would then be
class foo:
def foobar(self,):
f = foo()
...
Again, with more details about what you are trying to do it would be easier to help you.
Although it's unclear what you are asking, but the following changes do what you want to have.
But the code uses the instance of foo() not the class:
class bar:
def fooDef(self, fooObj):
print fooObj.fooNum
class foo:
def __init__(self):
self.fooNum = 1
b = bar()
f = self
b.fooDef(f)
f = foo()
Prints:
1

Python: looking for a short-hand way to setup setters/getters for lots of variables

I have one class (Bar) embedded inside another class (Foo).
class Foo():
class Bar():
def __init__(self):
self.a = 1
self.b = 2
...
self.z = 26
def __init__(self):
self.bar = Bar()
To access the attributes of class Bar, the user would need to the following:
>>> f = Foo()
>>> f.bar.a
1
How can I setup a short dot notation so that users can use BOTH:
>>> f.bar.a
1
and
>>> f.a
1
In my example, I'm trying to demonstrate that Bar class has a lot of variables. So I don't want to write a getter/setter for each one manually. So I was thinking to use the property() in a for loop like this:
def __init__(self):
self.bar = Bar()
# Allow shorter dot notation
for parm in self.bar.__dict__:
setattr(self, i, getattr(bar, i))
self.i = property(...)
But I'm unsure how to use property in this context without manually writing several setter functions.
Any suggestions on how to allow access to both shorter and longer notations?
That's what the __getattr__hook is ideally suited for:
class Foo:
# ...
def __getattr__(self, name):
return getattr(self.bar, name)
__getattr__ is only called for attributes that are missing; so only attributes that are not already present on instances of Foo() are passed to Foo().__getattr__(). The getattr() function then lets you use the same attribute name on self.bar; if the attribute doesn't exist there either, an AttributeError is thrown, as would be expected.

What is and isn't available to class methods in python?

My limited understand is that the second argument to types.FunctionTypes (dict) determines what is available to the function code. I'm curious how it gets gets decided when instantiating functions internally. To illustrate what I mean, if I try to copy a function dynamically:
a = 'test'
def foo():
print(a)
bar = types.FunctionType(
foo.__code__,
globals(),
'bar',
foo.__defaults__,
foo.__closure__
)
This seems to work fine with globals(), but am I missing anything? More confusing is a class method. If I do something like this:
a = 'test'
class Foo(object):
b = 'Foo prints this'
def myfunc():
print(a, self.b)
Bar = type('Bar', tuple(), dict())
Bar.b = 'Bar prints this'
ns = globals()
#should I do ns.update(something) here?
f = Foo.myfunc
Bar.myfunc = types.FunctionType(f.__code__, ns, 'myfunc', ...)
That example works, but not this more complicated one:
import imp
import builtins
class Foo(object):
def __init__(self):
super().__init__() # super(Foo, self) also fails
mod = imp.new_module('test')
mod.__builtins__ = builtins
mod.Foo = type('Foo', tuple(), dict())
f = Foo.__init__
ns = {}
ns.update(mod.__dict__) #missing something here
mod.Foo.__init__ = types.FunctionTypes(f.__code__, ns, '__init__', ...)
Could someone illuminate what should be in ns? What is available to a class method, and what isn't?
I'm not specifically trying to get the above code to work, I'm more looking for an explanation of why it doesn't.
The problem seems to be that "copying" the __closure__ attribute doesn't create a copy; that's the execution context in which the function body, (the def __init__) was itself executed; in support of the lexical scoping rules in the python language. Taking a look:
>>> [cell.cell_contents for cell in f.__closure__]
[<class '__main__.Foo'>]
Unsurprisingly, it's the class it was defined in. I'm not sure of a simple way of creating a new cell object besides using exec, to create a new class and method; You could probably copy the new cell around to additional methods to be added to the new class, but both the cell and the class would be brand new.

Categories