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
为什么您需要明确地拥有;“自我”;Python方法中的参数?_Python_Oop_Methods_Self - Fatal编程技术网

为什么您需要明确地拥有;“自我”;Python方法中的参数?

为什么您需要明确地拥有;“自我”;Python方法中的参数?,python,oop,methods,self,Python,Oop,Methods,Self,在Python中定义类上的方法时,其外观如下所示: class MyClass(object): def __init__(self, x, y): self.x = x self.y = y 但在其他一些语言中,例如C#,您可以使用“this”关键字对方法绑定到的对象进行引用,而无需在方法原型中将其声明为参数 这是Python中有意做出的语言设计决策,还是有一些实现细节需要传递“self”作为参数?这是为了最小化方法和函数之间的差异。它允许您轻松地在元

在Python中定义类上的方法时,其外观如下所示:

class MyClass(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y
但在其他一些语言中,例如C#,您可以使用“this”关键字对方法绑定到的对象进行引用,而无需在方法原型中将其声明为参数


这是Python中有意做出的语言设计决策,还是有一些实现细节需要传递“self”作为参数?

这是为了最小化方法和函数之间的差异。它允许您轻松地在元类中生成方法,或者在运行时将方法添加到预先存在的类中

e、 g


据我所知,它还使python运行时的实现更加容易。

我想引用Peters的python之禅。“显性比隐性好。”

在爪哇和C++中,可以推断“<代码>这个.<代码>”,除非你有不可推论的变量名。所以你有时需要,有时不需要

Python选择将这样的事情显式化,而不是基于规则


此外,由于没有暗示或假设任何内容,因此实现的某些部分是公开的<代码>self.\uuuuuu类\uuuuuuu,
self.\uuuuuuu dict\uuuuuuuuu
和其他“内部”结构显然是可用的。

还有另一个非常简单的答案:根据“显式优于隐式”。

Python不会强迫您使用“self”。你可以给它取任何名字。您只需记住,方法定义标题中的第一个参数是对对象的引用。

我建议您阅读本主题-

当一个方法定义被修饰时,我们不知道是否自动给它一个“self”参数:修饰器可以将函数转换成一个静态方法(没有“self”),或者一个类方法(有一种有趣的self,它引用一个类而不是一个实例),或者它可以做一些完全不同的事情(编写一个在纯Python中实现“@classmethod”或“@staticmethod”的修饰符是很简单的)。如果不知道修饰符做了什么,就无法知道是否为定义的方法赋予隐式“self”参数

我拒绝像特殊外壳“@classmethod”和“@staticmethod”这样的黑客攻击


我认为这与政治公众人物227有关:

类作用域中的名称不可访问。名称在 最内层的封闭函数作用域。如果类定义出现在 嵌套作用域链,解析过程跳过类 定义。此规则防止类之间的奇怪交互 属性和局部变量访问。如果是名称绑定操作 在类定义中发生,它将在生成的 类对象。在方法或函数中访问此变量 嵌套在方法中时,也必须使用属性引用 通过self或通过类名


还允许您这样做:(简而言之,调用
Outer(3)。创建\u internal\u类(4)()。带有\u closure\u作用域的怪异的\u sum\u(5)
将返回12,但会以最疯狂的方式返回

class Outer(object):
    def __init__(self, outer_num):
        self.outer_num = outer_num

    def create_inner_class(outer_self, inner_arg):
        class Inner(object):
            inner_arg = inner_arg
            def weird_sum_with_closure_scope(inner_self, num)
                return num + outer_self.outer_num + inner_arg
        return Inner
当然,在Java和C#等语言中,这是很难想象的。通过使自引用显式化,您可以通过该自引用自由引用任何对象。此外,在更静态的语言中,这样在运行时处理类的方式更难做到——这不一定是好的还是坏的。只是显式自引用允许所有这些疯狂的存在

此外,想象一下:我们想要定制方法的行为(用于分析,或一些疯狂的黑魔法)。这会让我们思考:如果我们有一个类
方法
,我们可以覆盖或控制它的行为会怎么样

好的,这是:

from functools import partial

class MagicMethod(object):
    """Does black magic when called"""
    def __get__(self, obj, obj_type):
        # This binds the <other> class instance to the <innocent_self> parameter
        # of the method MagicMethod.invoke
        return partial(self.invoke, obj)


    def invoke(magic_self, innocent_self, *args, **kwargs):
        # do black magic here
        ...
        print magic_self, innocent_self, args, kwargs

class InnocentClass(object):
    magic_method = MagicMethod()
从functools导入部分
类MagicMethod(对象):
“”“调用时是否使用黑魔法”“”
定义获取(自我、对象、对象类型):
#这会将类实例绑定到参数
#方法MagicMethod.invoke的
返回部分(self.invoke,obj)
def invoke(magic_self、innocent_self、*args、**kwargs):
#在这里做黑魔法
...
打印魔法自我、无辜自我、args、kwargs
类InnocentClass(对象):
magic_method=MagicMethod()
现在:
InnocentClass().magic_method()
将按预期运行。该方法将与
innocent\u self
参数绑定到
InnocentClass
,与
magic\u self
绑定到MagicMethod实例。奇怪吧?这就像在Java和C等语言中有两个关键字
this1
this2
。这样的魔法允许框架做一些否则会更加冗长的事情


同样,我不想评论这些东西的道德规范。我只是想展示一些如果没有明确的自我引用就很难做到的事情。

我认为除了“Python的禅宗”之外,真正的原因是函数是Python中的一流公民

现在的基本问题是,如果你的函数也是对象,那么在面向对象的范例中,当消息本身是对象时,你如何向对象发送消息

看起来像是一个鸡蛋问题,为了减少这种矛盾,唯一可能的方法是将执行上下文传递给方法或检测它。但是由于python可以有嵌套函数,因此不可能这样做,因为内部函数的执行上下文会发生变化

这意味着唯一可能的解决方案是显式传递“self”(执行上下文)

因此,我认为这是一个实施问题,禅宗的出现要晚得多。

如中所述 任何类似obj.meth(args)的东西都会变成Class.meth(obj,args)。调用过程是自动的,而接收过程不是(显式的)。这就是fu的第一个参数的原因
from functools import partial

class MagicMethod(object):
    """Does black magic when called"""
    def __get__(self, obj, obj_type):
        # This binds the <other> class instance to the <innocent_self> parameter
        # of the method MagicMethod.invoke
        return partial(self.invoke, obj)


    def invoke(magic_self, innocent_self, *args, **kwargs):
        # do black magic here
        ...
        print magic_self, innocent_self, args, kwargs

class InnocentClass(object):
    magic_method = MagicMethod()
class Point(object):
    def __init__(self,x = 0,y = 0):
        self.x = x
        self.y = y

    def distance(self):
        """Find distance from origin"""
        return (self.x**2 + self.y**2) ** 0.5
>>> p1 = Point(6,8)
>>> p1.distance()
10.0
class class_name:
    class_variable
    def method_name(self,arg):
        self.var=arg 
obj=class_name()
obj.method_name()