I don't understand why this code works, I think it should give an error but it doesn't:
class Person:
def __init__(self, name):
self.name = name
def greeting(self):
# Should return "hi, my name is " followed by the name of the Person.
return "hi, my name is "+self.name
def __str__(self):
return "str"
some_person = Person("foo")
print(print(some_person.greeting()))
In the __init__ method, I try to access a variable that is not actually defined (shouldn't be an error?)
and in the greeting method, I try to access that variable which is just defined in __init__ (shouldn't it be an error?). It doesn't give any error and works smoothly? how is that possible?
def __init__(self, name):
self.name =name
In fact, you tried to access a variable that is actually defined. name is defined in function parameter.
It shouldnt be an error! That's because self is the Object itself (you see why its called self?) so if you define something in the __init__ function, it is stored inside the object so you can use it from another function by peeling it off the object itself. The name variable you were talking about is defined in the function definition! Where you put __init__(self,name)
Related
This is the given code:
class Person:
def __init__(self, name):
self.name = name
def greeting(self):
return "hi, my name is " + self.name
some_person = Person("yeabsira")
print(some_person.greeting())
However, I was expecting the syntax in which the constructor method uses like:
class Name:
def __init__(self,atribute1,atribute2):
self.atribute1=atribute1
self.atribute2=atribute2
new_instance=Name("example")
print(new_instance.atribute1)
expect answer="example"
So my question is how "some_person.greeting()" symantic works?
some_person.name returns the value of the person's name, while some_person.greeting() returns a greeting with the name, it is just a function defined within the class Person and works normally like any other function. You could use some_person.name if you only need the name.
However, by using some_person.greeting(), you implemented data hiding, which hides internal object details, and the user (in the future) only needs to access greeting() and not the value of name itself.
I am trying to define static variables in this example code:
class test_object:
resolution_default_opts = {'e':{'ylims':[0,2],'xlabel':'resolution'},'t':{'ylog':True,'xlabel':'resolution'}}
ee_default_opts = {'eee':{'xlabel':'parameter number'}}
default_opts = {'resolution':test_object.resolution_default_opts,'ee':test_object.ee_default_opts}
def __init__(self,name):
self.name = name
def foo(self,input):
return default_opts[input]
an_instance = test_object('a_name')
print(an_instance.foo('ee'))
However when running the above I get the following error :
default_opts = {'resolution':test_object.resolution_default_opts,'ee':test_object.ee_default_opts}
NameError: name 'test_object' is not defined
My understanding is that the variables resolution_default_opts and ee_default_opts are static class variables and that I should be able to call them via test_object. or self., but evidently it is wrong.
What is causing this error and how could I still get foo to work as intended (ie return ee_default_ops when we input 'ee') ?
If it is relevant, the python version is : Python 3.8.10
Within the scope of the class definition, the class itself hasn't been defined yet (hence the NameError), but the class variables are in the local scope, so you can refer to them directly.
Within the scope of the method definition, the class variables aren't in the local scope, but at the time the method is executed the class has been defined so you can use that to refer to them (you can also use self).
class test_object:
resolution_default_opts = {'e':{'ylims':[0,2],'xlabel':'resolution'},'t':{'ylog':True,'xlabel':'resolution'}}
ee_default_opts = {'eee':{'xlabel':'parameter number'}}
default_opts = {'resolution':resolution_default_opts,'ee':ee_default_opts}
def __init__(self, name):
self.name = name
def foo(self, i):
return test_object.default_opts[i]
an_instance = test_object('a_name')
print(an_instance.foo('ee'))
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'
I am python Begineer and i learned that first parameter inside the method should be contain some 'self' keyword but i found the following program runs without self keyword can you explain about this below is my code...
class Student(object):
def __init__(self,name,age):
self.name = name
self.age = age
def get_biggest_number(*age):
result=0
for item in age:
if item > result:
result= item
return result
Sam = Student("Sam",18)
Peter = Student("Peter",20)
Karen = Student("Karen",22)
Mike = Student("Michael",21)
oldest= Student.get_biggest_number(Sam.age,Peter.age,Karen.age,Mike.age)
print (f"The oldest student is {oldest} years old.")
Code you've posted has indentation errors within it, you should first indent methods and it's content, meaning that, methods are within class. On the other hand, self refers to instance, which calls specific method and gives access to the all instance data. For example
student1 = Student('name1', 20)
student2 = Student('name2', 21)
student1.some_method(arg1)
in the last call, behind the scenes student1 is passed for self parameter of the method, meaning that all student1's data is available through self argument.
What you are trying is to use staticmethod, which has no data of the instance and is aimed to logically group class related functions without explicit instance, which does not require self in method definition:
class Student:
...
#staticmethod
def get_biggest_number(*ages):
# do the task here
On the other hand, if you would like to track all student instances and apply get_biggest_number method automatically work on them, you just have to define class variable (rather than instance variable) and on each instance __init__ append new instance to that list:
class Student:
instances = list() # class variable
def __init__(self, name, age):
# do the task
Student.instances.append(self) # in this case self is the newly created instance
and in get_biggest_number method you just loop through Student.instances list which will contain Student instance and you can access instance.age instance variable:
#staticmethod
def get_biggest_number():
for student_instance in Student.instances:
student_instance.age # will give you age of the instance
Hope this helps.
You shouldn't mistake classmethod with instance methods.
In python you can declare a method inside a class as classmethod.
This method takes a reference to the class as the first argument.
class Student(object):
def __init__(self,name,age):
self.name = name
self.age = age
def get_biggest_number(self, *age):
result=0
for item in age:
if item > result:
result= item
return result
#classmethod
def get_classname(cls):
# Has only access to class bound items
# gets the class as argument to access the class
return cls.__name__
#staticmethod
def print_foo():
# has not a reference to class or instance
print('foo')
self in python refers to the instance of the class that is created. Something like this in C# and Java. However there's some differences but in short: when you don't use self as input of a method, actually you're saying that this method does not need any instance, that means this method is a static method and will never use any of class attributes.
In your example we can call get_biggest_number method with not even one instance, for example you can call this method just like this:
Student.get_biggest_number(20,30,43,32)
and the output will be 43.
The self keyword is used to represent an instance (object) of the given class. ... However, since the class is just a blueprint, self allows access to the attributes and methods of each object in python.
class ClassA:
def methodA(self, arg1, arg2):
self.arg1 = arg1
self.arg2 = arg2
let say ObjectA is an instance of the class.
Now when ObjectA.methodA(arg1, arg2) is called, python internally converts it as:
ClassA.methodA(ObjectA, arg1, arg2)
The self variable refers to the object itself and the code becomes as:
class ClassA:
def methodA(ObjectA, arg1, arg2):
ObjectA.arg1 = arg1
ObjectA.arg2 = arg2
I have some functionality wrapped up in a Python class (classa). classa inherits from another class supera.
I want exactly the same functionality as classa except that I want to inherit from superb.
I could just copy the class classa to a new class classb and then change the superclass for classb but obviously this very tacky, a maintenance headache and and I'm quite sure there's much better way - can anyone tell me what it is ?
EDIT: Thanks for answers so far. I should have said initially the my classa invokes super in its methods in order to invoke supera methods. It seems that this has some significance when looking at mixins as an option
This can be done with Python's multiple inheritance if none of the methods need to invoke super().
class Dog(object):
name = "Spot"
class Cat(object):
name = "Whiskers"
class SpeakingAnimalMixin(object):
def speak(self):
print "My name is", self.name, "and I can speak!"
class SpeakingDog(SpeakingAnimalMixin, Dog):
pass
class SpeakingCat(SpeakingAnimalMixin, Cat):
pass
SpeakingDog().speak()
My name is Spot and I can speak!
If you do need to invoke super() from a method then you need to create the class dynamically. This works fine, but the generated class's name will be less helpful and IDEs and other static analysis tools may be less useful.
You can create the class using a function, passing the superclass as an argument:
def make_speaking_animal_class(SpeechlessAnimal):
class SpeakingAnimal(SpeechlessAnimal):
def get_name(self):
return "Speaking " + super(SpeakingAnimal, self).get_name()
def speak(self):
print "My name is", self.get_name()
return SpeakingAnimal
class Dog(object):
def get_name(self):
return "Spot"
class Cat(object):
def get_name(self):
return "Whiskers"
SpeakingDog = make_speaking_animal_class(Dog)
SpeakingCat = make_speaking_animal_class(Cat)
SpeakingCat().speak()
My name is Speaking Whiskers
However as mentioned, the class's __name__ attribute may not be what you expect.
print SpeakingDog
print SpeakingDog()
<class '__main__.SpeakingAnimal'>
<__main__.SpeakingAnimal object at 0x1004a3b50>
You can fix this by assigning them unique __name__ attributes yourself:
SpeakingDog.__name__ = 'SpeakingDog'
print SpeakingDog
<class '__main__.SpeakingDog'>
(Credit to Andrew Jaffe for suggesting this in an answer, but he deleted it.)
There's another way to create a class dynamically, but I discourage you from using it unless you need to; it's even less clear. The type function has a second use, apart from its main one of determining the class of an object: it can be used to dynamically create a new class.
When used this way, the type function takes three parameters:
name, the __name__ the new class will have.
bases, a tuple of of base classes that the new class will inherit from.
dict, a dictionary containing the methods and attributes the new class will have.
You could use it like this:
def make_speaking_animal_class(SpeechlessAnimal, name):
def get_name(self):
return "Speaking " + super(SpeakingAnimal, self).get_name()
def speak(self):
print "My name is", self.get_name()
bases = (SpeechlessAnimal,)
# We need to define SpeakingAnimal in a variable so that get_name can refer
# to it for the super() call, otherwise we could just return it directly.
SpeakingAnimal = type(name, bases, {
'get_name': get_name,
'speak': speak
})
return SpeakingAnimal
class Dog(object):
def get_name(self):
return "Spot"
class Cat(object):
def get_name(self):
return "Whiskers"
SpeakingDog = make_speaking_animal_class(Dog, 'SpeakingDog')
SpeakingCat = make_speaking_animal_class(Cat, 'SpeakingCat')
SpeakingDog().speak()
SpeakingCat().speak()
My name is Speaking Spot
My name is Speaking Whiskers