使用 class 方法在 PYTHON class 中分配属性值
Assigning an attribute value in a PYTHON class with class methods
这是一个与设置属性相关的非常基本的问题,我没有找到明确的答案。
我有一个 python class 如下
class circle():
PI = 3.14
def __init__(self,radius):
self.radius = radius
# 1. first way of assigning an atribute
self.area = self._area()
# 2. second way of assigning an attribute (running a method)
self._squarearea(self.radius,self.area)
# 3. third way of assigning an attribute
self.diameter = self._diameter(self.radius)
def _area(self):
return self.radius * self.PI * self.PI
def _squarearea(self,radius,area):
self.sqarea = radius * radius * 4 - area
def _diameter(self,radius):
return self.radius *2
def giveme4timesradius(self):
return 4*self.radius
我列出了 4 种分配属性或计算数据的方法。
在我的特定真实示例中,每个方法都执行复杂的计算,这些计算最好为了阅读代码的目的而保持分隔。
我做的每一个作业都有一定的缺点
方式 1:self.area = self._area()
。
reader 现在在 init 方法中没有多少变量占用空间来进行计算。 class 方法是 运行,但是 reader 必须深入研究代码以查看计算的内容以及如何计算
方式 2:self._squarearea(self.radius,self.area)
在这种情况下,reader 不知道函数的作用,即使函数设置了新属性也不知道。相反,至少表明半径和面积被传递给函数。实际上传递的两个变量只是一个指示,因为在 class 方法中所有 class 属性都可用。
方式 3:self.diameter = self._diameter(self.radius)
这里的reader知道半径是通过的,也知道分配了一个属性(直径)
方式四:
最后一种方法可以考虑为 class 的消费者提供调用方法 giveme4timesradius()
的方法,但这很不方便,因为我希望所有这些都预先计算过。而且每次调用都要计算。
有多个关于属性和 classes 和教程的 SO 问题(见下文),但我没有在任何地方看到这种比较。
我想我不需要任何 setter 和 getter 因为我只想从一开始就 运行 ,根据倍数条件一些属性将用一些 class 来计算方法或其他。
那么“pythonic”方式有哪些呢?或者其中任何一个?
参考文献:
https://www.toptal.com/python/python-class-attributes-an-overly-thorough-guide
https://realpython.com/lessons/adding-attributes-python-class/
https://www.python-course.eu/python3_class_and_instance_attributes.php
https://medium.com/shecodeafrica/managing-class-attributes-in-python-c42d501c5ee0
正如您所说,第二个选项令人困惑,因为您需要转到方法定义才能了解 class 实例中对新变量的赋值。从这个意义上说,第一个选项更清楚一些,但我仍然想知道该方法的必要输入参数是什么。
然而,第三个选项是错误的,原因有二。第一,你传递了半径但你仍然访问 self.radius,所以这个参数是多余的。第二,即使你使用了参数,它也应该是一个用@staticmethod修饰的静态方法,因为你没有使用class实例(self).
因此,我会使用一个静态方法,它利用它需要的适当输入变量。类似于:
class Circle:
PI = 3.14
def __init__(self, radius):
self.radius = radius
self.area = self.compute_area(self.radius)
@staticmethod
def compute_area(radius):
return radius * (Circle.PI**2)
这是 @property
装饰器的一个很好的用例。
class Circle():
PI = 3.14
def __init__(self,radius):
self.radius = radius
@property
def area(self):
return self.radius * (self.PI ** 2)
@property
def squarearea(self):
return (self.radius ** 2) * 4 - self.area
@property
def diameter(self):
return self.radius *2
@property
def giveme4timesradius(self):
return 4*self.radius
此外,根据我的喜好,我会使用@dataclass:
from dataclasses import dataclass
from typing import ClassVar
@dataclass
class Circle():
radius: float
PI: ClassVar[float] = 3.14
# No need __init__ -> handled by dataclass
@property
def area(self):
return self.radius * (self.PI ** 2)
@property
def squarearea(self):
return (self.radius ** 2) * 4 - self.area
@property
def diameter(self):
return self.radius *2
@property
def giveme4timesradius(self):
return 4*self.radius
这是一个与设置属性相关的非常基本的问题,我没有找到明确的答案。 我有一个 python class 如下
class circle():
PI = 3.14
def __init__(self,radius):
self.radius = radius
# 1. first way of assigning an atribute
self.area = self._area()
# 2. second way of assigning an attribute (running a method)
self._squarearea(self.radius,self.area)
# 3. third way of assigning an attribute
self.diameter = self._diameter(self.radius)
def _area(self):
return self.radius * self.PI * self.PI
def _squarearea(self,radius,area):
self.sqarea = radius * radius * 4 - area
def _diameter(self,radius):
return self.radius *2
def giveme4timesradius(self):
return 4*self.radius
我列出了 4 种分配属性或计算数据的方法。 在我的特定真实示例中,每个方法都执行复杂的计算,这些计算最好为了阅读代码的目的而保持分隔。
我做的每一个作业都有一定的缺点
方式 1:
self.area = self._area()
。 reader 现在在 init 方法中没有多少变量占用空间来进行计算。 class 方法是 运行,但是 reader 必须深入研究代码以查看计算的内容以及如何计算方式 2:
self._squarearea(self.radius,self.area)
在这种情况下,reader 不知道函数的作用,即使函数设置了新属性也不知道。相反,至少表明半径和面积被传递给函数。实际上传递的两个变量只是一个指示,因为在 class 方法中所有 class 属性都可用。方式 3:
self.diameter = self._diameter(self.radius)
这里的reader知道半径是通过的,也知道分配了一个属性(直径)方式四: 最后一种方法可以考虑为 class 的消费者提供调用方法
giveme4timesradius()
的方法,但这很不方便,因为我希望所有这些都预先计算过。而且每次调用都要计算。
有多个关于属性和 classes 和教程的 SO 问题(见下文),但我没有在任何地方看到这种比较。 我想我不需要任何 setter 和 getter 因为我只想从一开始就 运行 ,根据倍数条件一些属性将用一些 class 来计算方法或其他。
那么“pythonic”方式有哪些呢?或者其中任何一个?
参考文献:
https://www.toptal.com/python/python-class-attributes-an-overly-thorough-guide
https://realpython.com/lessons/adding-attributes-python-class/
https://www.python-course.eu/python3_class_and_instance_attributes.php
https://medium.com/shecodeafrica/managing-class-attributes-in-python-c42d501c5ee0
正如您所说,第二个选项令人困惑,因为您需要转到方法定义才能了解 class 实例中对新变量的赋值。从这个意义上说,第一个选项更清楚一些,但我仍然想知道该方法的必要输入参数是什么。
然而,第三个选项是错误的,原因有二。第一,你传递了半径但你仍然访问 self.radius,所以这个参数是多余的。第二,即使你使用了参数,它也应该是一个用@staticmethod修饰的静态方法,因为你没有使用class实例(self).
因此,我会使用一个静态方法,它利用它需要的适当输入变量。类似于:
class Circle:
PI = 3.14
def __init__(self, radius):
self.radius = radius
self.area = self.compute_area(self.radius)
@staticmethod
def compute_area(radius):
return radius * (Circle.PI**2)
这是 @property
装饰器的一个很好的用例。
class Circle():
PI = 3.14
def __init__(self,radius):
self.radius = radius
@property
def area(self):
return self.radius * (self.PI ** 2)
@property
def squarearea(self):
return (self.radius ** 2) * 4 - self.area
@property
def diameter(self):
return self.radius *2
@property
def giveme4timesradius(self):
return 4*self.radius
此外,根据我的喜好,我会使用@dataclass:
from dataclasses import dataclass
from typing import ClassVar
@dataclass
class Circle():
radius: float
PI: ClassVar[float] = 3.14
# No need __init__ -> handled by dataclass
@property
def area(self):
return self.radius * (self.PI ** 2)
@property
def squarearea(self):
return (self.radius ** 2) * 4 - self.area
@property
def diameter(self):
return self.radius *2
@property
def giveme4timesradius(self):
return 4*self.radius