为什么有些方法使用点符号而其他方法不使用?
Why do some methods use dot notation and others don't?
所以,我才刚刚开始学习Python(使用Codecademy),有点迷茫。
为什么有些方法采用参数,而另一些方法使用点符号?
len() 接受一个参数,但不适用于点符号:
>>> len("Help")
4
>>>"help".len()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'len'
同样:
>>>"help".upper()
'HELP'
>>>upper("help")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'upper' is not defined
这里的关键词是方法。函数和方法之间存在细微差别。
方法
是在给定对象的class中定义的函数。例如:
class Dog:
def bark(self):
print 'Woof woof!'
rufus = Dog()
rufus.bark() # called from the object
函数
一个函数是一个全局定义的过程:
def bark():
print 'Woof woof!'
至于你关于len
函数的问题,全局定义的函数调用对象的__len__
特殊方法。所以在这种场景下,就是一个可读性的问题。
否则,当方法只适用于某些对象时会更好。当函数应用于多个对象时会更好。例如,如何将数字大写?您不会将其定义为函数,而是将其定义为仅在字符串 class 中的方法。
您所说的 "dot notation" 是 class 方法,它们仅适用于具有 class 实现者定义的方法的 classes。 len
是一个内置函数,它接受一个参数和 returns 该对象的大小。如果 class 愿意,它可能会实现一个名为 len
的方法,但大多数情况下不会。内置 len
函数有一个规则,如果 class 有一个名为 __len__
的方法,它将使用它,所以这个工作:
>>> class C(object):
... def __len__(self):
... return 100
...
>>> len(C())
100
"help".upper
则相反。字符串 class 定义了一个名为 upper
的方法,但这并不意味着还必须有一个名为 upper
的函数。原来在string
模块中有一个upper
函数,但是一般情况下你不需要因为实现了一个class方法就额外实现一个函数。
这是函数和方法之间的区别。如果您只是学习基础知识,也许可以简单地接受这个区别是存在的,你最终会明白的。
还在吗?实际上,这甚至都不难。在面向对象的编程中,方法在很多方面都优于函数,因为这意味着一种类型的对象可以覆盖 其 版本的方法而不影响系统的其余部分。
例如,假设您有一种新的字符串,当您调用 .upper()
时,重音字符应该失去重音。这种类型的实例可以 subclass str
并且在其他方面的行为完全相同,基本上是免费的;他们需要重新定义的只是 upper
方法(即便如此,也可能调用基础 class 的方法,并且只在处理重音小写字符时更改逻辑)。预计在字符串上工作的软件将继续工作,如果你传入一个需要标准 str
的新类型的对象,甚至不知道有什么区别。
Python 中的一个设计原则是 一切都是对象。 这意味着您甚至可以为 object
这样的基本对象创建自己的替代品、class
和 type
,即扩展或覆盖您的应用程序或平台的基本语言。
事实上,这发生在 Python 2 中,当时 unicode
字符串被引入语言。许多应用程序软件继续像以前一样工作,但现在有 unicode
个实例,而以前的代码是为处理 str
个实例而编写的。 (这种差异在 Python 3 中不再存在;或者更确切地说,称为 str
并且几乎无处不在的类型现在称为 bytes
并且仅在您特别想要处理时使用不是文本的数据。)
回到我们新的upper
方法,想想相反的情况;如果 upper
只是标准库中的一个函数,你怎么会考虑修改需要 upper
以不同方式运行的软件?如果明天您的老板希望您为 lower
做同样的事情怎么办?这将是一项艰巨的任务,您必须对整个代码库进行的更改很容易导致意大利面条式结构,并且可能会引入细微的新错误。
这是面向对象编程的基石之一,但当您在更结构化的介绍中学习其他两三个原则时,它可能只有 真正 有意义。现在,也许快速而粗略的总结是 "methods make the implementation modular and extensible."
所以,我才刚刚开始学习Python(使用Codecademy),有点迷茫。
为什么有些方法采用参数,而另一些方法使用点符号?
len() 接受一个参数,但不适用于点符号:
>>> len("Help")
4
>>>"help".len()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'len'
同样:
>>>"help".upper()
'HELP'
>>>upper("help")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'upper' is not defined
这里的关键词是方法。函数和方法之间存在细微差别。
方法
是在给定对象的class中定义的函数。例如:
class Dog:
def bark(self):
print 'Woof woof!'
rufus = Dog()
rufus.bark() # called from the object
函数
一个函数是一个全局定义的过程:
def bark():
print 'Woof woof!'
至于你关于len
函数的问题,全局定义的函数调用对象的__len__
特殊方法。所以在这种场景下,就是一个可读性的问题。
否则,当方法只适用于某些对象时会更好。当函数应用于多个对象时会更好。例如,如何将数字大写?您不会将其定义为函数,而是将其定义为仅在字符串 class 中的方法。
您所说的 "dot notation" 是 class 方法,它们仅适用于具有 class 实现者定义的方法的 classes。 len
是一个内置函数,它接受一个参数和 returns 该对象的大小。如果 class 愿意,它可能会实现一个名为 len
的方法,但大多数情况下不会。内置 len
函数有一个规则,如果 class 有一个名为 __len__
的方法,它将使用它,所以这个工作:
>>> class C(object):
... def __len__(self):
... return 100
...
>>> len(C())
100
"help".upper
则相反。字符串 class 定义了一个名为 upper
的方法,但这并不意味着还必须有一个名为 upper
的函数。原来在string
模块中有一个upper
函数,但是一般情况下你不需要因为实现了一个class方法就额外实现一个函数。
这是函数和方法之间的区别。如果您只是学习基础知识,也许可以简单地接受这个区别是存在的,你最终会明白的。
还在吗?实际上,这甚至都不难。在面向对象的编程中,方法在很多方面都优于函数,因为这意味着一种类型的对象可以覆盖 其 版本的方法而不影响系统的其余部分。
例如,假设您有一种新的字符串,当您调用 .upper()
时,重音字符应该失去重音。这种类型的实例可以 subclass str
并且在其他方面的行为完全相同,基本上是免费的;他们需要重新定义的只是 upper
方法(即便如此,也可能调用基础 class 的方法,并且只在处理重音小写字符时更改逻辑)。预计在字符串上工作的软件将继续工作,如果你传入一个需要标准 str
的新类型的对象,甚至不知道有什么区别。
Python 中的一个设计原则是 一切都是对象。 这意味着您甚至可以为 object
这样的基本对象创建自己的替代品、class
和 type
,即扩展或覆盖您的应用程序或平台的基本语言。
事实上,这发生在 Python 2 中,当时 unicode
字符串被引入语言。许多应用程序软件继续像以前一样工作,但现在有 unicode
个实例,而以前的代码是为处理 str
个实例而编写的。 (这种差异在 Python 3 中不再存在;或者更确切地说,称为 str
并且几乎无处不在的类型现在称为 bytes
并且仅在您特别想要处理时使用不是文本的数据。)
回到我们新的upper
方法,想想相反的情况;如果 upper
只是标准库中的一个函数,你怎么会考虑修改需要 upper
以不同方式运行的软件?如果明天您的老板希望您为 lower
做同样的事情怎么办?这将是一项艰巨的任务,您必须对整个代码库进行的更改很容易导致意大利面条式结构,并且可能会引入细微的新错误。
这是面向对象编程的基石之一,但当您在更结构化的介绍中学习其他两三个原则时,它可能只有 真正 有意义。现在,也许快速而粗略的总结是 "methods make the implementation modular and extensible."