方法覆盖?

Method Overriding?

我看到了这段代码:

def g(x,y):
    return x+y
def g(x,y):
    return x*y
x,y=6,7
print (g(x,y))

输出显然(但对我来说不是)是 42。有人可以解释一下这种行为吗?我想这是方法重写,但我仍然没有得到这里的流程。

问题在于函数定义的顺序。

这在技术上不是方法覆盖,因为它需要 class 继承,而是 python 声明和引用函数的结果。

声明函数时,python 将对该函数的引用存储在以函数定义命名的变量中。 (例如,对于 "def foo():",变量将是 "foo")

通过两次声明该函数,该变量的值将被第二个定义覆盖。

当你定义一个函数,然后重新定义它,它会使用你最后定义的,即使参数不同:

def g(x,y):
    return x+y
def g(x,y):
    return x*y
x,y=6,7
print (g(x,y))

def hello():
    return 'hello'
def hello():
    return 'bye'

print hello()

def withone(word):
    return word

def withone():
    return 1==1

print withone('ok')

输出:

42
bye
TypeError: withone() takes no arguments (1 given)

而 Python 中的函数名更像是简单的变量:

def hello():
    return 'hello'

iamhello = hello # bind to the old one

def hello():
    return 'bye'

print hello() # here is the new guy

print iamhello()

输出:

bye
hello

顺序很重要,如果名称相同,则您定义的最后一个函数正在处理。在你的情况下是;

def g(x,y):
    return x*y

g 只是一个变量。它所引用的对象是一个函数这一事实并没有使它在 Python 中变得特殊,因此您可以根据需要对其进行分配和重新分配。在这种情况下,第二个赋值(即函数定义)只是用另一个对象替换存储在那里的对象。

一个Python脚本从上到下解析。 因此,只要出现相同名称的变量或函数或 class,它就会覆盖之前与该名称关联的所有定义。

def g(x,z):
    print('first')

def g():
    print('second')

g = 3
print g
print g()

所以看看这个例子,它会导致打印输出“3”,然后出现异常:'TypeError: 'int' object is not callable'

名字g最初是一个有两个参数的函数,然后它被重新定义为一个没有参数的函数,然后它被重新定义为一个int。 显然不能调用 :)

函数和方法与其他任何对象一样都是普通对象。所以在

def g(x, y):
    return x + y

def g(x, y):
    return x * y    

第二个对象 g 将覆盖(替换)第一个对象,就像下面对象 a 所做的那样:

a = 1
a = 2

参数的数量、类型或顺序没有任何区别,因为Python不支持function/method覆盖并且不允许两个functions/methods同名。

如果您熟悉 lambda function,也经常称为 anonymous\inline 函数,这可能会让事情变得更清楚一些

这两个代码块本质上是相等的

def g(x,y):
    return x+y
def g(x,y):
    return x*y

g = lambda x,y:  x+y
g = lambda x,y:  x*y

python 中的所有内容都被视为对象,无论是函数名称还是 class 名称。所以,当我们使用 'def' 定义一个函数时,内存分配是为该方法完成的。然后 python 将我们分配给函数的名称指向这个分配的内存位置。所以如果我们定义一个方法:-

def demo():
    print 'hi'

为方法分配内存,名称'demo'指向其内存位置如下:-

现在,正如 在他的第二个示例中所描述的那样,当您将函数名称分配给另一个变量时:-

demo2 = demo # bind to the old one

那么在这种情况下,分配给 demo 的内存位置也被分配给 demo2。所以 demodemo2 都指向同一个位置 12506.

print id(demo)   # will print 12506
print id(demo2)  # will print 12506

现在如果我们修改上面的代码并在下一行中定义一个同名的新方法demo:-

def demo():
    print 'hi'

demo2 = demo # bind to the old one
demo()       # Will print hi

def demo():
    print "hello"

demo()      # Will print hello
demo2()     # Will print hi

然后为这个新方法分配了一个全新的内存位置 12534,现在 demo 将指向这个新位置 12534 而不是指向旧位置,即12506。但是 demo2 仍然指向位置 12506.

我希望这能让您清楚地了解正在发生的事情以及方法名称如何 over-written。