我是Python的新手。我不明白如何/为什么使用self
参数:
class Person:
def __init__(self, name):
self.name = name
def sayHi(self):
print 'Hello, my name is', self.name
p = Person('Swaroop')
p.sayHi()
此代码来自Python的Byte。这段代码可以很容易地编写为:
def sayHi(self, name):
print 'Hello, my name is', name
p = Person('Swaroop')
p.sayHi()
...对吧?将name
字段设为self
的目的是什么?
答案 0 :(得分:6)
似乎你过分简化了一件不那么简单的事情。 在面向对象的编程中,Class是一个声明构造,它给出了一个蓝图,说明对象(这个蓝图的一种表现形式)将包含什么(属性)以及它将如何表现(成员)。 这种类的每个表现形式都称为对象,它具有已定义的特定实例。从一个对象通过任何称为成员函数/方法的行为属性,我们需要以某种方式引用该对象的实例并记住其中的各个元素,并与其他非成员实体明确区分。
考虑你的例子
class Person:
def __init__(self, name):
self.name = name
def sayHi(self):
print 'Hello, my name is', self.name
此人的每个实例(Tom,Dick,Harry)都是独一无二的,并且在每个实例中,为了回顾自身,我们需要一些习惯用法(在Python中自我,这个ptr是C ++或Java中的这个)。
因此,在__init__
方法中,当您需要使用name
参数在Person的name
属性之间划分时,我们可以使用self
轻松完成此操作。不仅如此,在任何情况下,我们都可以通过self
继续引用此名称。
创建Person p=Person('Swaroop')
的实例,然后调用sayHi,与仅调用一个不是对象一部分的函数sayHi形成对比有两个含义
sayHi
将意味着一个物理上存在的Swaroop问候回到他的名字,他有一个持久的记忆,除非他采用新的名字,否则永远不会忘记。 如果你有C ++的背景,可能想知道为什么我们需要在函数调用中添加那个额外的参数,而在C ++中这个指针永远不会传递。
坦率地说它确实如此。如果您阅读C ++调用约定,无论是X86还是X64,那么this指针将通过寄存器ecx
传递给方法,以便为自己提供句柄。这里更明确的是我们故意将句柄传递给方法的当前实例。
答案 1 :(得分:4)
查看新方法sayHiTo
:
class Person:
def __init__(self, name):
self.name = name
def sayHi(self):
print 'Hello, my name is', self.name
def sayHiTo(self, other):
print 'Hello', other.name, ' my name is', self.name
p1 = Person('Swaroop')
p2 = Person('codeninja')
p1.sayHiTo(p2)
p2.sayHiTo(p1)
答案 2 :(得分:2)
其实没有。你的第二个例子不正确。 'self'关键字是一个特殊的引用,它被传递给类的实例方法。它表示该范围内类的实际实例。当你上课时,它只是一般定义。然后,您创建该类的实例。每个实例都是唯一的,因此方法必须能够在该实例上工作。在制作之前你无法了解它们,所以“自我”会为你传递它们。
例如,如果您创建了person person的两个实例:
p1 = Person("john")
p2 = Person("sam")
每个人的self.name值都不同。当你在每个实例上调用sayHi()时:
p1.sayHi()
> Hello, my name is john
p2. sayHi()
> Hello, my name is sam
您不会将self关键字用于未绑定的函数。也就是说,只是像你的第二个例子所写的一般功能。你必须像这样写它;
def sayHi(name):
print 'Hello, my name is', name
p = Person('Swaroop')
p.sayHi()
> sayHi("john")
但这基本上只是将一个名称字符串传递给Person类并调用其方法。这里的想法是您使用自己的属性创建Person的唯一实例。
答案 3 :(得分:0)
目的是存储对名称的引用,以便您可以在该类的另一种方法中引用它,例如def sayHi (self)
答案 4 :(得分:0)
您无法将类中的函数与函数进行比较。当然你可以传递名字,但使用类的想法是你封装数据。将vars链接到self意味着您可以传递一个对象,并且该对象始终可以访问其“成员变量”。其他一些类可以使用Person的实例,而不需要知道那些人的名字才能说出来。