Python 创建属性时使用构造函数参数的正确方法
在创建其他属性时,是否有正确的方法使用构造函数参数?例如: 在创建Python 创建属性时使用构造函数参数的正确方法,python,oop,Python,Oop,在创建其他属性时,是否有正确的方法使用构造函数参数?例如: 在创建self.arg4时,是否使用shape=arg3.shape或shape=self.arg3.shape import numpy as np class MyClass: def __init__(self, arg1, arg2, arg3=None, arg4=None): self.arg1 = arg1 self.arg2 = arg2 if arg3 is
self.arg4
时,是否使用shape=arg3.shape
或shape=self.arg3.shape
import numpy as np
class MyClass:
def __init__(self, arg1, arg2, arg3=None, arg4=None):
self.arg1 = arg1
self.arg2 = arg2
if arg3 is None:
self.arg3 = np.array([[10, 10], [10, 10]])
else:
self.arg3 = arg3
if (arg3 is None) and (arg4 is None):
self.arg4 = np.ones(shape=(2,2))
elif arg4 is None:
print('Look at this case')
self.arg4 = np.ones(shape=self.arg3.shape)
# OR
self.arg4 = np.ones(shape=arg3.shape)
else:
self.arg4 = arg4
def print_args(self):
print(self.arg1)
print(self.arg2)
print(self.arg3)
print(self.arg4)
if __name__ == '__main__':
x = np.array([[25, 20], [20, 25]])
my_obj = MyClass(arg1=3, arg2=4, arg3=x)
my_obj.print_args()
根据输出结果,我猜这两种方法的效果是一样的,但我正在寻找一个答案,解释最佳实践是什么(如果有的话)及其背后的OOP推理。您应该这样做
self.arg4 = np.ones(shape=self.arg3.shape)
这纯粹是为了增加代码的可读性
self.arg4 = np.ones(shape=arg3.shape)
你可以自由做任何你喜欢的事,但这只是我的意见。
shape=arg3.shape
和shape=self.arg3.shape
都不一样
在第一个示例中,使用指向构造函数中的参数的arg3.shape
。
在第二个示例中,您使用的是指向类的实例变量的self.arg3.shape
。
因此,应该使用self访问所有实例变量。
参数中的变量不应使用self。根据构造函数中给出的特定输入,这两条指令
shape=arg3.shape
和shape=self.arg3.shape
是不同的,它们不一定会产生相同的输出。让我解释一下原因:
- 每当访问方法内的变量时,如果在关键字
前面加上前缀,则引用对象范围内定义为全局变量的对象变量李>self
- 如果未在关键字
前加前缀,则引用函数范围内的任何变量(例如self
),该变量不一定与对象内的全局变量匹配\uuuu init\uuuu
self.arg3
计算self.arg4
,那么正确的指令是shape=self.arg3.shape
你为什么要预先编写self
?
简而言之,self
取消引用存储对象的内存,该内存位于进程堆中:对象变量在此活动
相反,函数存在于堆栈中(作为函数变量):它不知道对象在哪里,因此不知道其变量在堆中的位置。这就是为什么在Python3.8.3上必须使用
self
,它运行时没有任何错误。您知道为什么“任何属于该实例的变量都应该通过将self.pre置于其之前来访问”吗?这是python中类的工作方式。但是在这里,您有一个名为arg3的参数和一个名为arg3的实例变量,所以任何东西都可以工作。但我个人发现,如果使用带有参数值的实例变量,则更容易理解。这只是一个可读性目的。因为它处于初始化阶段,这真的很重要吗?在参数中使用self
变量是错误的。它会抛出错误。在您的情况下,它可以工作,因为您定义了arg3
变量,该变量是实例变量。因此,当您执行self.arg3
时,它使用的是属于类的arg3变量。如果只执行arg3
,它将使用构造函数参数中的值。对构造函数中的变量和实例变量使用不同的名称。你会更好地理解的。你的回答给了我很多见解。但是在这种情况下,由于我在\uuuu init\uuuu()
方法中,这真的很重要吗?或者使用prependself
甚至在\uuuu init\uuuu()内部使用也是一种很好的编程实践?因为我纯粹是基于传入构造函数的参数初始化对象变量(即\uuuu init\uuuu()
),所以这很重要。要初始化一个对象变量,您必须在self
前面加上前缀:方法与其他方法相比没有任何特殊之处,并且中没有self
的变量被视为一个函数变量,它将被“弹出”只要\uuuu init\uuuu
返回,就会从堆栈和整个函数堆栈中删除。我知道要初始化arg4,我必须使用self.arg4
,我在这两种情况下都使用过。但是,我的问题是为什么我应该使用self.arg3.shape
而不是arg3.shape
来查找arg3
行中self.arg4=np.one(shape=self.arg3.shape)
的形状。因为它在\uuuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu,然后将self.arg3
设置为等于arg3
。因此,当您设置print
语句时,两个变量都指向同一个obj。