Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/grails/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 创建属性时使用构造函数参数的正确方法_Python_Oop - Fatal编程技术网

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()
方法中,这真的很重要吗?或者使用prepend
self
甚至在
\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。