How to use class methods in python? - python

I have this code
class Person(object):
def __init__(self, name):
self.name = name
#classmethod
def from_classmethod(cls, name):
return cls(name)
p = Person.from_classmethod("Moctar")
p.name
But it shows the following error:
AttributeError: 'Person' object has no attribute 'name'
What could be going wrong here, or am i using wrongly the python #classmethod feature ?

As #furas says, what I think you want is:
class Person(object):
def __init__(self, name):
self.name = name
#classmethod
def from_classmethod(cls, name):
return cls(name)
p = Person.from_classmethod("Moctar")
print(p.name)
Result:
Moctar
It is the assignment to self.name that creates that attribute on the instance of Person that you are creating.

Related

How to format strings in classes using attributes?

I want to format an attribute-string of a class with another attribute of the same class like this:
class Test:
def __init__(self):
self.name = None
self.full_name = 'name, {}'.format(self.name)
def print_name(self):
print(self.full_name)
my_object = Test()
my_object.name = 'my_object'
my_object.print_name()
Now it should print 'name, my_object'
But it prints 'name, None'
What to do that the string formats with the assigned value of the object?
You need to add full_name as a property so that you can add some more logic to it:
class Test:
def __init__(self):
self.name = None
#property
def full_name(self):
return f'name, {self.name}'
def print_name(self):
print(self.full_name)
my_object = Test()
my_object.name = 'my_object'
my_object.print_name()
Resources:
property function (built-in)

transform class methods using parent class' decorator method

def greeting_decorator(original_function):
def return_function(*args):
name = 'John'
return f'Hi, I\'m {name}, fullname: {original_function(*args)}'
return return_function
#greeting_decorator
def greeting(name, surname):
return f'{name} {surname}'
print(greeting('John', 'Doe'))
Above, I have a simple decorator function that works as intended.
I'd like to do something similar, but with an inherited class.
How might I go about inheriting a decorator function like this:
class Guy:
def __init__(self, name):
self.name = 'John'
def greeting_decorator(self, original_function):
def return_function(*args):
return f'Hi, I\'m {self.name}, fullname: {original_function(*args)}'
return return_function
class GuyWithSurname(Guy):
def __init__(self, name, surname):
super().__init__(name)
self.surname = surname
#greeting_decorator # <----- here
def __str__(self):
return f'{self.name} {self.surname}'
JohnDoe = GuyWithSurname('John', 'Doe')
print(JohnDoe)
If you are certain that the parent class will always be Guy, you can simply annotate via #Guy.greeting_decorator:
class Guy:
def __init__(self, name):
self.name = 'John'
def greeting_decorator(original_function):
def return_function(self, *args):
return f'Hi, I\'m {self.name}, fullname: {original_function(self, *args)}'
return return_function
class GuyWithSurname(Guy):
def __init__(self, name, surname):
super().__init__(name)
self.surname = surname
#Guy.greeting_decorator # <----- here
def __str__(self):
return f'{self.name} {self.surname}'
JohnDoe = GuyWithSurname('John', 'Doe')
That way, when you call print(JohnDoe) it will output Hi, I'm John, fullname: John Doe.
Note that I had to change the greeting_decorator and the return_function parameters to properly handle self.

TypeError: 'str' object is not callable oop

Im new to oop with python. Why am I getting this error? Shouldnt it print tom and 12?
class Dog:
def __init__(self,name,age):
self.name = name
self.age = age
def name(self):
return self.name
def age(self):
return self.age
dog = Dog("tom", 12)
print(dog.name())
print(dog.age())
Instance attributes take precedence over class attributes when one of each exists and they have the same name. If you are going to have a method that returns the value of an attribute, a common convention is to make the name of the instance attribute a "private" version of the method name by prefixing an underscore to the name.
class Dog:
def __init__(self, name, age):
self._name = name
self._age = age
def name(self):
return self._name
def age(self):
return self._age
However, until you have a good reason to hide the attribute behind a getter, just expose the attribute as part of the public interface.
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
d = Dog("tom", 12)
print(dog.name)
If you later decide to hide the attribute behind a getter and/or setter, you can use a property to do so without changing the public interface.
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age
#property
def name(self):
return self._name
#name.setter
def name(self, v):
self._name = v
d = Dog("tom", 12)
print(dog.name) # Works the same as before
name is a variable and name is also a function.
Therefore this error.
Just do print(self.name)
you have to create class and change the name of funtion like this
class Dog:
def __init__(self,name,age):
self.name = name
self.age = age
def Name(self):
return self.name
def age(self):
return self.age
dog = Dog("tom", 12)
print(dog.name())
print(dog.age())

Override property

In a base class I'm creating a property with property() function:
from abc import ABCMeta, abstractmethod
class Person(metaclass=ABCMeta):
#abstractmethod
def __init__(self, name, telephone):
self.name = name
self.telephone = telephone
def get_name(self) -> str:
return self.__name
def set_name(self, value: str):
self.__name = value
name = property(fget=get_name, fset=set_name)
And in the derived class I need to override the set_name method, that is, Person.name.fset should point to a modified version of the method. I tried this but it did not work:
class Employee(Person):
def __init__(self, name, telephone, email):
super().__init__(name, telephone)
self.email = email
def set_name(self, value):
super().set_name('override')
Person.name.fset = set_name
Is there any way to override property in python?

Is it allowed to use subclass constructor in Python

As in the title. In example:
class A:
def __init__(self,name):
self.name=name
class B(A):
def __init__(self,surname):
self.surname=surname
obj=B('somename','somesurname')
If it's allowed, in which order shall I pass parameters in object instantiation?
You need to explicitly call the constructor of the super-class from your derived one:
class A:
def __init__(self,name):
self.name=name
class B(A):
def __init__(self, name, surname):
super().__init__(name)
self.surname=surname
obj=B('somename','somesurname')
You should use super builtin function:
class A:
def __init__(self, name):
self.name=name
class B(A):
def __init__(self, name, surname):
super().__init__(name)
self.surname=surname
obj=B('somename','somesurname')
Your new constructor should call the parent constructor if the old constructor must be executed. You can call the parents constructor using super:
class A:
def __init__(self, name):
self.name = name
class B(A):
def __init__(self, name, surname):
super().__init__(name)
self.surname = surname
obj = B('somename', 'somesurname')
In python 2, you must specify the current class and self as arguments to super(): super(B, self), in python 3 it can be called without arguments like as shown above.

Categories