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())
Related
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)
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.
Let's consider the following example:
class SubClass:
def __init__(self):
self._param = None
#property
def param(self):
print('read param')
return self._param
#param.setter
def param(self, value):
print('set param')
self._param = value
class MainClass:
def __init__(self):
self._var = SubClass()
#property
def var(self):
print('read var')
return self._var
#var.setter
def var(self, value):
print('set var')
self._var = value
If I do:
cls = MainClass()
cls.var.param = 3
I obtain:
'read var'
'set param'
How can I make MainClass aware that var.param has changed?
Useful additional info: consider that in my actual code param is not a scalar but an array with hundreds of elements, so I would like to avoid to create a copy and then just compare them. Moreover, param and var are not the only properties.
One approach is to pass a method from MainClass as an argument when instantiating SubClass, and have SubClass call it whenever it changes a variable:
class SubClass:
def __init__(self, changed):
self._param = None
self.changed = changed
#property
def param(self):
print('read param')
return self._param
#param.setter
def param(self, value):
print('set param')
self._param = value
self.changed('param')
class MainClass:
def __init__(self):
self._var = SubClass(self.changed)
def changed(self, name):
print("Subclass changed: ", name, getattr(self._var, name))
#property
def var(self):
print('read var')
return self._var
#var.setter
def var(self, value):
print('set var')
self._var = value
m = MainClass()
m.var.param = 'test'
I have two unittest classes in the same file which look like this:
class A(unittest.TestCase):
def some_fun(param):
# Set class parameters
self.foo = param + 100
...
def some_fun2():
do_something with self.foo
self.assertEqual(self.foo,<check>)
def some_fun3():
do_something
def setUp(self):
some_fun(some_foo1)
def test1(self):
some_fun2(some_foo1)
def tearDown(self):
some_fun3(some_foo1)
class B(unittest.TestCase):
def some_fun(param):
# Set class parameters
self.foo = param + 100
...
def some_fun2():
do_something with self.foo
self.assertEqual(self.foo,<check>)
def some_fun3():
do_something
def setUp(self):
some_fun(some_foo1)
def test1(self):
some_fun2(some_foo1)
def tearDown(self):
some_fun3(some_foo1)
I want to move some_fun, some_fun2, some_fun3 outside to reduce code repetition keeping in mind that these functions can have assert checks
What is the best way to do this? Im not sure how to do inheritance in this scenario
Edit:
I am facing this weird issue
class X(unittest.TestCase):
def __init__(self, foo):
print(foo) # why is foo=somefun
def test():
<something>
class A(X):
FOO = "SOMESTRING"
def setUp(self):
super().__init__(A.FOO)
def somefun(self):
self.test()
It can be like this:
class X(unittest.TestCase):
def some_fun(self, param):
# Set class parameters
self.foo = param + 100
...
def some_fun2(self):
do_something with self.foo
self.assertEqual(self.foo,<check>)
def some_fun3():
do_something
class A(X):
def setUp(self):
self.some_fun(some_foo1)
def test1(self):
self.some_fun2(some_foo1)
def tearDown(self):
self.some_fun3(some_foo1)
class B(X):
def setUp(self):
self.some_fun(some_foo1)
def test1(self):
self.some_fun2(some_foo1)
def tearDown(self):
self.some_fun3(some_foo1)
Inheritance rules apply normally here. Create a base class with the methods you want that inherits from TestCase:
class BaseTest(unittest.TestCase):
def some_fun(self):
...
def some_fun2(self):
...
Create A and B inheriting from BaseTest:
class A(BaseTest):
def test1(self):
...
class B(BaseTest):
def test2(self):
...
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.