AttributeError resulting from function defined in class definition - python

I am trying to learn how to define classes in Python, starting by creating a very basic example:
class CustomClass:
def print_class(self):
print(self)
CustomClass = 'Hello World'
CustomClass.print_class()
Yet when I run this, I get the error:
AttributeError: 'str' object has no attribute 'print_class'
I don't want to try to access or define some attribute of this class. I want to run the function defined when the class is defined. Could someone point out what I am doing wrong?

what do you wanted to do with this statement: CustomClass = 'Hello World'
if you want to instantiate an object of that class you need to do something like this:
name_of_object = CustomClass() # create an object
name_of_object.print_class() # this will call the method in that class

There is no self in a stand-alone function. If you define a class and instantiate it, self will refer to that object. You’re trying to use an attribute of a class object in the context of no object.
Example:
class Test(object):
def __init__(self, text):
self.text = text
def print_me(self):
print(self.text)
o = Test(‘Hello world’)
o.print_me()
Try that.

Fixed Code:
class CustomClass:
def print_class(self):
print(self)
myClass = CustomClass()
myClass.print_class()

Related

Instantiating and Using a Method of a Class Within a Function

I'm trying to instantiate a class within a function, then call a method within the class inside the same function, like this:
# Define the class
class myclass:
def __init__(self,string_to_print):
self.string_to_print = string_to_print
def myclass_func(self):
print(self.string_to_print)
# Define the function that utilizes the class
def func(class,func,str)
instance = class(str)
class = class.func()
# Run the function that utilizes the class
func(myclass,myclass_func,str)
But I am getting an error like "'myclass' object is not callable". Why is this? Additionally, I expect my 'class = class.func()' line is wrong; if it is, what is the correct way to call the method from the recently instantiated class?
Edit: fixed mistake in class declaration
You can't use method names as global variables. If you want to call a method dynamically, pass its name as a string and use the getattr() function.
# Define the class
class myclass:
def __init__(self,string_to_print):
self.string_to_print = string_to_print
def myclass_func(self):
print(self.string_to_print)
# Define the function that utilizes the class
def func(class,func,str)
instance = class(str)
return getattr(instance, func)()
# Run the function that utilizes the class
func(myclass,'myclass_func',str)
Define your class using the class keyword rather than def.
Create an instance of the class.
Define a function that will try to execute the function given by its name.
class myclass:
def __init__(self,string_to_print):
self.string_to_print = string_to_print
def myclass_func(self):
print(self.string_to_print)
myclass_instance = myclass('Hello world')
def execute_function(instance, function):
getattr(instance, function)()
execute_function(myclass_instance, 'myclass_func')
Output:
Hello world

Is there a way to call specific classes based on a variable?

I want a program to call a specific class based on a parameter/variable value. However, I don't want to use any clunky if-statements. My first thought was to use the globals() function, but I couldn't get it to work. Here's an example:
class SomeClass:
def __init__():
print("Hello, world!")
class OtherClass:
def runClass(className):
# Call class based on variable className
The reason I want to do this is because there is a wide variety of classes may need to be called, and so just piling up if-statements in my code won't do it. Any help would be greatly appreciated. Thanks!
Here's how you can call a class via globals
class SomeClass:
def __init__(self):
print("Hello, world!")
def __call__(self):
return "SomeClass called"
class OtherClass:
def runClass(self, className):
globals()[className]()()
o = OtherClass()
result = o.runClass("SomeClass")
print(result)
Notice, I am instantiating and then calling it via the __call__ special method, which is the closest match to your description I could think of.
Use a dict.
name_to_class = dict(some=SomeClass,
other=OtherClass)
def factory(name):
klass = name_to_class(name)
return klass()
some_obj = factory("some")
other_obj = factory("other")
One way to solve this problem is to use a dictionary to map the values of the variable className to the corresponding class.
Try this exemple :
class SomeClass:
def init(self):
print("Hello, world!")
class OtherClass:
def init(self):
print("Goodbye, world!")
classNameToClass = {
"SomeClass": SomeClass,
"OtherClass": OtherClass
}
def runClass(className):
# Call class based on variable className
cls = classNameToClass[className]
return cls()
runClass("SomeClass") # prints "Hello, world!"
runClass("OtherClass") # prints "Goodbye, world!"
Here, the dictionary classNameToClass maps the string names of the classes (e.g. "SomeClass") to the corresponding class objects (e.g. SomeClass). Then, in the runClass function, we look up the class object using the value of the className variable, and call it to create an instance of the class.
I've found an answer. The parameter that governs the called class can just be assigned elsewhere. At first, I thought it would need some complex function, but in reality, I guess the question didn't give enough details. The class itself only uses items from whatever object is given. So, instead of having to dynamically call a class, it's as simple as:
class SomeClass:
def printHelloWorld():
print("Hello, world!")
class OtherClass:
def __init__(self, usingClass):
self.object = usingClass
def doThis():
usingClass.printHelloWorld()
x = OtherClass(SomeClass())
x.doThis()
It's on me for not giving enough information. Thank you all for your help.

Is there a way to turn a class object name into the string associated with it?

So in my program, a certain function (good_function()) needs to use the string name (attribute_name) of an object when referencing an attribute(object_name.attribute) of an object(object_name). This attribute is also another object from a different class. However, when I pull out this attribute to be used, it brings up the class object name (<main.Class2 object at abcde12345>) instead of the name of the attribute (attribute_name). The current output and setup is as follows.
class Class():
def __init__(self, attribute):
pass
class Class2():
pass
attribute_name = Class2()
object_name = Class(attribute_name)
object_name.attribute = attribute_name
def good_function(thing):
#doesn't really matter
pass
good_function(object_name.attribute)
print(object_name.attribute)
>>> <__main__.Class2 object at abcde12345>
It reads "object_name.attribute"(attribute_name) "as the attribute_name"'s object ID name thingamajiggy (<main.Class2 object at abcde12345>) instead of just "attribute_name". So my question is: Is there a way to translate the callsign (<main.Class2 object at abcde12345>) into the "attribute name" to which it corresponds? (see desired output below) Thanks in advance, I hope this wasn't too confusing, and I'll be as active as I can in responses. The desired output and setup is below.
cclass Class():
def __init__(self, attribute):
pass
object_name.attribute = 'attribute_name'
def magic_function(object):
#solve for here
return object
def good_function(thing):
#doesn't really matter
pass
variable = magic_function(object_name.attribute)
good_function(variable)
print(variable)
>>> attribute_name
If I'm understanding correctly, then I don't think what you want is possible, assuming the actual reference attribute is just a native type.
However, if you made the attribute an instance of your own custom class then any instance could implement the __str__ method to display whatever you wanted:
class MyClass():
def __str__(self):
return 'MyClass str'

Python inheritance program

Error is:
Equilateral object has no attribute angle1.
please suggest how to fix this error and also please explain how self works. I am confused where to use self and where to not
class Triangle(object):
number_of_sides=3
def __init__(self,angle1,angle2,angle3):
self.angle1=angle1
self.angle2=angle2
self.angle3=angle3
def check_angles(self):
if self.angle1+self.angle2+self.angle3==180:
return True
else:
return False
class Equilateral(Triangle): //inheritance
angle=60
def __init__(self):
self.angle=self.angle1
self.angle=self.angle2
self.angle=self.angle3
man=Equilateral()
man.check_angles()
You have it the wrong way around
self.angle1= self.angle
etc
Self refers to the instantiated object, much like 'this' in java. You attach attributes to the object using this keyword.
When defining variables on an object, attributes at the beginning of your class definition do not need self- they are class attributes which all instances of the object will create on instantiation, whereas variables you change or set using self are instance variables and not found on all instances of the object.
Different from other languages, Python does not call __init__() of the super class. You have to call it yourself:
class Equilateral(Triangle):
angle=60
def __init__(self, ...):
super().__init__(...)
self.angle=self.angle1
More details
You have to call __init__ from the super class:
class Triangle(object):
number_of_sides=3
def __init__(self,angle1,angle2,angle3):
self.angle1=angle1
self.angle2=angle2
self.angle3=angle3
def check_angles(self):
return self.angle1+self.angle2+self.angle3==180:
class Equilateral(Triangle):
angle=60
def __init__(self):
Triangle.__init__(self, self.angle, self.angle, self.angle)
man=Equilateral()
man.check_angles()

How do I set and access attributes of a class? [duplicate]

This question already has answers here:
How can I access "static" class variables within methods?
(6 answers)
Closed 12 days ago.
Suppose I have this code:
class Example(object):
def the_example(self):
itsProblem = "problem"
theExample = Example()
print(theExample.itsProblem)
When I try it, I get an error that says:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Example' object has no attribute 'itsProblem'
How do I access this attribute? I tried adding another method to return it:
def return_itsProblem(self):
return itsProblem
but the problem persists.
The answer, in a few words
In your example, itsProblem is a local variable.
Your must use self to set and get instance variables. You can set it in the __init__ method. Then your code would be:
class Example(object):
def __init__(self):
self.itsProblem = "problem"
theExample = Example()
print(theExample.itsProblem)
But if you want a true class variable, then use the class name directly:
class Example(object):
itsProblem = "problem"
theExample = Example()
print(theExample.itsProblem)
print (Example.itsProblem)
But be careful with this one, as theExample.itsProblem is automatically set to be equal to Example.itsProblem, but is not the same variable at all and can be changed independently.
Some explanations
In Python, variables can be created dynamically. Therefore, you can do the following:
class Example(object):
pass
Example.itsProblem = "problem"
e = Example()
e.itsSecondProblem = "problem"
print Example.itsProblem == e.itsSecondProblem
prints
True
Therefore, that's exactly what you do with the previous examples.
Indeed, in Python we use self as this, but it's a bit more than that. self is the the first argument to any object method because the first argument is always the object reference. This is automatic, whether you call it self or not.
Which means you can do:
class Example(object):
def __init__(self):
self.itsProblem = "problem"
theExample = Example()
print(theExample.itsProblem)
or:
class Example(object):
def __init__(my_super_self):
my_super_self.itsProblem = "problem"
theExample = Example()
print(theExample.itsProblem)
It's exactly the same. The first argument of ANY object method is the current object, we only call it self as a convention. And you add just a variable to this object, the same way you would do it from outside.
Now, about the class variables.
When you do:
class Example(object):
itsProblem = "problem"
theExample = Example()
print(theExample.itsProblem)
You'll notice we first set a class variable, then we access an object (instance) variable. We never set this object variable but it works, how is that possible?
Well, Python tries to get first the object variable, but if it can't find it, will give you the class variable. Warning: the class variable is shared among instances, and the object variable is not.
As a conclusion, never use class variables to set default values to object variables. Use __init__ for that.
Eventually, you will learn that Python classes are instances and therefore objects themselves, which gives new insight to understanding the above. Come back and read this again later, once you realize that.
You are declaring a local variable, not a class variable. To set an instance variable (attribute), use
class Example(object):
def the_example(self):
self.itsProblem = "problem" # <-- remember the 'self.'
theExample = Example()
theExample.the_example()
print(theExample.itsProblem)
To set a class variable (a.k.a. static member), use
class Example(object):
def the_example(self):
Example.itsProblem = "problem"
# or, type(self).itsProblem = "problem"
# depending what you want to do when the class is derived.
If you have an instance function (i.e. one that gets passed self) you can use self to get a reference to the class using self.__class__
For example in the code below tornado creates an instance to handle get requests, but we can get hold of the get_handler class and use it to hold a riak client so we do not need to create one for every request.
import tornado.web
import riak
class get_handler(tornado.web.requestHandler):
riak_client = None
def post(self):
cls = self.__class__
if cls.riak_client is None:
cls.riak_client = riak.RiakClient(pb_port=8087, protocol='pbc')
# Additional code to send response to the request ...
Implement the return statement like the example below! You should be good. I hope it helps someone..
class Example(object):
def the_example(self):
itsProblem = "problem"
return itsProblem
theExample = Example()
print theExample.the_example()
If you have a #classmethod static method, you always have the class as the first parameter:
class Example(object):
itsProblem = "problem"
#classmethod
def printProblem(cls):
print(cls.itsProblem)
Example.printProblem()

Categories

Resources