subclass for NameError: name 'side_length' is not defined - python-3.x

class Polygon():
def __init__(self, side_lengths):
self.side_lengths = side_lengths
def perimeter(self):
return sum(self.side_lengths)
def __str__(self):
side_lengths = len(self.side_lengths)
return 'Polygon with {} sides'.format(side_lengths)
class Triangle(Polygon):
def __init__(self, side_lengths):
super().__init__(side_lengths)
def area(self):
s = sum(self.side_lengths)/2
a = self.side_lengths[0]
b = self.side_lengths[1]
c = self.side_lengths[2]
return float((s*(s-a)*(s-b)*(s-c)) ** 0.5)
def __str__(self):
return 'Triangle, Area: {:.2f} units^2, Perimeter: {:.2f} units'.format(self.area(), self.perimeter())
class Rectangle(Polygon):
def __init__(self, side_lengths):
super().__init__(side_lengths)
def area(self):
return float(self.side_lengths[0]*self.side_lengths[1])
def __str__(self):
return 'Rectangle, Area: {:.2f} units^2, Perimeter: {:.2f} units'.format(self.area(), self.perimeter())
class Square(Rectangle):
def __init__(self, side_length):
self.side_length = side_length
def area(self):
return float(4*side_length)
def __str__(self):
return 'Square, Area: {:.2f} units^2, Perimeter: {:.2f} units'.format(self.area(), self.perimeter())
For this program, I want to calculate the area of the square when the input of side_length is a float instead of a list, but name error occurs. How to deal with such issue?
class Square(Rectangle):
def __init__(self,side_length):
super().__init__(side_length)
I also tried this method, it does not work as well.

Related

Question about setter and calling MyClass()

I have a class like this:
class A:
b = ""
#property
some_property(self):
raise Error()
#some_property.setter
def some_property(self, some_property_var)
self.b = some_property_var
and i want to do A(some_property='A'), but i can't because
TypeError: A() takes no arguments
. Is there any way to make it work?
I think this is a better example of how to demonstrate what you are trying to do;
#set a property in a class in python
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
#property
def name(self):
return self._name
#name.setter
def name(self, name):
self._name = name
#property
def age(self):
return self._age
#age.setter
def age(self, age):
self._age = age
p = Person("John", 36)
So in your case;
class A:
def __init__(self, b):
self.b = b
#property
def b(self):
return self._b
#b.setter
def b(self, b):
self._b = b
a = A(1)
print(a.b)
Based on your comments;
#create a class that takes keyword arguments
class A:
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
a = A(a=1, b=2)

Factory design pattern using __init_subclass__ python3

I didn't find any info about the implementation of the factory design pattern using __init_subclass__ to register the product and the class. What do you think about?
https://peps.python.org/pep-0487/
class Shape:
product = None
shapes_classes = {}
def __init_subclass__(cls, **kwargs):
cls.shapes_classes[cls.product] = cls
#classmethod
def create_shape(cls, product, *args, **kwargs):
return cls.shapes_classes[product](*args, **kwargs)
def __str__(self):
return f'I am {self.__class__.__name__} shape'
def area(self):
raise NotImplemented
class Triangle(Shape):
product = 'triangle'
def __init__(self, base, height):
self.base = base
self.height = height
def area(self):
return self.height * self.base / 2
class Square(Shape):
product = 'square'
def __init__(self, base, ):
self.base = base
def area(self):
return self.base ** 2
#Usage:
Shape.shapes_classes
{'triangle': __main__.Triangle, 'square': __main__.Square}
triangle = Shape.create_shape(product='triangle',base=3,height=4)
square=Shape.create_shape(product='square',base=3)
print(triangle)
I am Triangle shape
print(square)
I am Square shape
triangle.area()
6.0
square.area()
9

How to Access Outer class variables in Inner Class (Python)?

How to access the variables of the outer class in the Inner Class?
class Student:
def __init__(self,Name,rollNumber):
self.Name=Name
self.rollNumber=rollNumber
self.lap=self.Laptop()
def Show(self):
print(self.Name)
print(self.lap.show())
class Laptop:
def __init__(self):
self.brand = "Mac"
self.cpu = "i9"
self.ram = 16
def show(self):
return self.brand
#staticmethod
def Show():
return s1.Name
s1=Student("Teja",2)
print(s1.Name,s1.rollNumber)
s1.Show()
print(s1.lap.brand)
system=s1.lap
print(system.brand)
print(system.cpu)
print(system.show())
print(system.Show())

My output is printing incorrectly and I can't seem to understand why

Here's my code.
I thought I did everything right, and this is my last resort
class Vehicle(object):
def __init__(self, make, model, year=2000):
self.make = make
self.model = model
self.year = year
#property
def year(self):
return self._year
#year.setter
def year(self, year):
self.year = None
if (year > 2000 and year < 2018):
self._year = year
#property
def make(self):
return self._make
#make.setter
def make(self, value):
self._make = value
#property
def model(self):
return self._model
#model.setter
def model(self, value):
self._model = value
class Truck(Vehicle):
def __init__(self, make, model, name=None):
Vehicle.__init__(self, make, model, name)
self.name = name
#property
def name(self):
return self._name
#name.setter
def name(self, value):
self._name = value
class Car(Vehicle):
def __init__(self, make, model, name=None):
Vehicle.__init__(self, make, model, name)
self.name = name
#property
def name(self):
return self._name
#name.setter
def name(self, value):
self._name = value
class DodgeRam(Truck):
make = "Dodge"
model = "Ram"
def __init__(self, year):
Truck.__init__(self, year, DodgeRam.make, DodgeRam.model)
self.year = year
#property
def year(self):
return self._year
#year.setter
def year(self, year):
self._year = year
class HondaCivic(Car):
make = "Honda"
model = "Civic"
def __init__(self, year):
Car.__init__(self, year, HondaCivic.make, HondaCivic.model)
self.year = year
#property
def year(self):
return self._year
#year.setter
def year(self, year):
self._year = year
ram = DodgeRam(2016)
print(ram)
civic1 = HondaCivic(2007)
print (civic1)
civic2 = HondaCivic(1999)
print (civic2)
Output - this is where im confused.
What causes an output like this instead of a straight up error?
<main.DodgeRam object at 0x000001F04AB1A848>
<main.HondaCivic object at 0x000001F04AAA73C8>
<main.HondaCivic object at 0x000001F04AAA7DC8>
Expected Output -
2016 Dodge Ram
2007 Honda Civic
2000 Honda Civic
Welcome, Mr. Soup, to stack overflow and to Python!!!
The simple answer to your question (if I understand it correctly) to get the print that you desire, is to override Python's str method. I've shown an example below. Also, I've done a few code cleanups that I hope you will find helpful.
Note that in Python, you don't assign properties (setters/getters) unless you explicitly need to interrupt them (as with year). In other languages you do (Java, C#), but not Python.
class Vehicle(object):
def __init__(self, make: str, model: str, year: int = 2000):
self.make = make
self.model = model
self.year = year
#property
def year(self):
return self._year
#year.setter
def year(self, year):
if year < 1999 or year > 2019:
raise ValueError
self._year = year
def __str__(self):
return f"{self.year} {self.make} {self.model}"
class Truck(Vehicle):
def __init__(self, make, model, year):
super().__init__(make, model, year)
class Car(Vehicle):
def __init__(self, make, model, year):
super().__init__(make, model, year)
class DodgeRam(Truck):
def __init__(self, year):
super().__init__("Dodge", "Ram", year)
class HondaCivic(Car):
def __init__(self, year):
super().__init__("Honda", "Civic", year)
if __name__ == '__main__':
ram = DodgeRam(2016)
print(ram)
civic1 = HondaCivic(2007)
print(civic1)
civic2 = HondaCivic(1999)
print(civic2)

Override abstract setter of property in Python 3

What is the simplest / most pythonic way to override only the setter of an abstract property in Python 3? Variant 3 seems to mean the least effort for the derived class implementor. Is it correct? Does it have disadvantages?
import abc
class A1(metaclass=abc.ABCMeta):
def __init__(self, x, **kwargs):
super().__init__(**kwargs)
self._x = x
#property
def x(self):
return self._x
#x.setter
#abc.abstractmethod
def x(self, value):
self._x = value
class B1(A1):
#property
def x(self):
return super().x
#x.setter
def x(self, value):
print("B1 setter")
super(B1, self.__class__).x.fset(self, value)
b1 = B1(x=1)
b1.x = 3
print(b1.x)
class A2(metaclass=abc.ABCMeta):
def __init__(self, x, **kwargs):
super().__init__(**kwargs)
self._x = x
#abc.abstractmethod
def _get_x(self):
return self._x
#abc.abstractmethod
def _set_x(self, value):
self._x = value
x = property(_get_x, _set_x)
class B2(A2):
def _get_x(self):
return super()._get_x()
def _set_x(self, value):
print("B2 setter")
super()._set_x(value)
x = property(_get_x, _set_x)
b2 = B2(x=1)
b2.x = 3
print(b2.x)
class A3(metaclass=abc.ABCMeta):
def __init__(self, x, **kwargs):
super().__init__(**kwargs)
self._x = x
def _get_x(self):
return self._x
#abc.abstractmethod
def _set_x(self, value):
self._x = value
x = property(
lambda self: self._get_x(),
lambda self, value: self._set_x(value))
class B3(A3):
def _set_x(self, value):
print("B3 setter")
super()._set_x(value)
b3 = B3(x=1)
b3.x = 3
print(b3.x)
So, yes, you listed a lot of ways in there - and although the one that requires more code is your variant 3, the most straighforard, least surprising way to do it is your variant 1 -
It just works, and is perfectly readable, no surprises - and there seems to be no simpler way than calling fget explicitly there.

Resources