您的位置:首页 > 编程语言 > Python开发

Python中function和method

2018-02-03 00:55 507 查看
这两个概念已经有很多人解释过了,从本文的『参考』中就可以看出来。之所以还要写一篇这个主题,主要是为了用自己的语言表述一下,并且尽可能的讲的清楚一点。

泛泛地说,function是一般意义上的函数,即对一段代码的封装,并由一个地址(函数名)来调用。

method通常是面向对象的概念,即method是属于一个类或类的对象的。method是与类或类的对象相关的函数。

下面讲一下我对这两个概念的更具体的理解。如有错误,敬请指正。

在C语言中『function』翻译为『函数』(C函数)。在Java中一般不使用『function』,而是改用『method』来称呼函数,『method』翻译为『方法』(Java方法)。

在Python中,你会同时看到『function』和『method』,所以Google的Python Style Guide中也对『function』和『method』分别进行了命名规则说明

TypePublicInternal解释
Functionslower_with_under()_lower_with_under()如果允许外部模块调用,命名采用小写字母加下划线(不以下划线开头)。
如果不允许外部调用,则命名以下划线开头,表示私有。
Method Nameslower_with_under()_lower_with_under() (protected) or __lower_with_under() (private)如果对外公开(外部可调用),则命名为小写字母加下划线,且不以下划线开头。
如果不对外公开,命名以一个下划线开头(protected)或者以以2个下划线开头(private)。注意:这里的protected和private与C++中的访问策略不一样。python中所谓的protected和private函数都是可以被调用的。更多内容,请见『参考』
Function/Method Parameterslower_with_underfunction或者method的参数,命名采用小写字母加下划线
在Python中,『function』就是一般意义上的函数,『method』是与类相关的函数,从概念上说,『function』和『method』都是函数,且『method』是『function』的子集。注意,这只是从概念上说,实际上,python中『function』和『method』是不同的类型,有
class function
class method
之分(python3中)。

在Python中用
def
定义的都是函数。在类内定义的函数,通常来说是method,但也可能是function。这要看如何使用这个函数。总结一下,我对python中『function』和『method』的理解,如下:

如果一个函数(
def
定义的)是不用依赖类的实例就可以调用,那么这个函数就是function类型的。例如,类的静态方法(
@staticmethod
),或者直接通过类名来调用类里声明的非静态函数,形式如
ClassX.funcA()


如果一个函数(
def
定义的)必须要依赖类的实例才能执行,那么此函数就是method类型的。例如,通过类的实例调用的方法,形式如
ClassX().funcA()
. (与上面的区别是括号:
ClassX()
ClassX
的区别)

如果一个函数(
def
定义的)依赖类本身,那么此函数是method类型的。这类函数是通过
@classmethod
修饰的类方法,因为类方法的第一个参数必须是类本身。注意,类方法的第一个参数不是类的实例(对象)

注意:以上结论是通过分析python3的代码得出的,与python2的会有些差异。

注意:除非有特别说明,以下代码的运行环境为Python3。

★ 1. function or mthod

一个普通函数的例子

>>> def func():
...     return 0
...
>>> type(func)
<class 'function'>


直接通过类名调用类内的非静态函数

>>> class ClassB(object):
...     def func():
...             return 'hello'
...
>>> ClassB.func()
'hello'


在类内部声明了函数(funcB),如果通过类直接访问funcB,其类型为function。如果通过类实例访问funcB,则其类型为method。

>>> class ClassB(object):
...     def funcB(self):
...             return 1
...
>>> type(ClassB.funcB)
<class 'function'>
>>> type(ClassB().funcB)
<class 'method'>


ClassB.funcB
ClassB().funcB
是不同的类型。所以调用的方式也是不同的。

>>> ClassB.funcB(None)  #function类型,不用创建实例,直接调用
1
>>> ClassB.funcB(ClassB()) #function类型,实例在参数中传入
1
>>> ClassB().funcB()    #method类型,创建实例,然后调用
1


如果通过ClassB的实例去调用
funcB()
ClassB().funcB()
),此时
funcB
就是method类型。

如果通过ClassB类直接调用
funcB()
ClassB.funcB()
),此时
funcB
是function类型。

注意:在Python2.7.1中,与Python3不同。类里面声明的方法,就是实例方法。不是function类型。

在Python2.7.1中运行

>>> class ClassC:
...     def func(self):
...             return 2
...
>>> ClassC.func
<unbound method ClassC.func>
>>> type(ClassC.func)
<type 'instancemethod'>   # 注意,这里不是function类型
>>> type(ClassC().func)
<type 'instancemethod'>


★ 2. 『@classmethod』

声明一个classmethod

>>> class ClassE(object):
...     @classmethod
...     def funcE(cls, arg1, arg2):
...             return arg1 + arg2
...


调用classmethod有两种方式

直接通过类来调用

通过类的实例来调用

>>> ClassE.funcE(1,2)
3
>>> ClassE().funcE(1,2)
3


classmethod修饰的函数的类型总是method类型:

>>> type(ClassE.funcE)
<class 'method'>
>>> type(ClassE().funcE)
<class 'method'>


看看classmethod的第一个参数:

>>> class ClassE(object):
...     @classmethod
...     def funcE(cls, arg1, arg2):
...             print(cls)
...             return arg1 + arg2
...


像上面那样调用,结果如下。可以看到
funcE
的第一个参数是
ClassE
类型,注意不是ClassE的实例(对象)

>>> ClassE.funcE(1,2)
<class '__main__.ClassE'>
3
>>> ClassE().funcE(1,2)
<class '__main__.ClassE'>
3


♦ 2.1 classmethod的一种用法:用来创建类的实例(对象),类似构造函数。

>>> class ClassE(object):
...     def __init__(self, str, arg1, arg2):
...             self.str = str
...             print(str)
...     @classmethod
...     def funcE(cls, arg1, arg2):
...             obj = cls('hello world', arg1, arg2)
...             return obj
...


创建ClassE的实例

>>> obj = ClassE.funcE(1, 2)
hello world # 调用了ClassE的初始化函数,返回的obj是ClassE的实例(对象)
>>> obj.str
'hello world'


classmethod的官方说明:https://docs.python.org/3/library/functions.html#classmethod

stackoverflow上对classmethod的解释:https://stackoverflow.com/questions/12179271/meaning-of-classmethod-and-staticmethod-for-beginner

★ 3. 『@staticmethod』

声明一个staticmethod的函数:

>>> class ClassD(object):
...     @staticmethod
...     def func(arg1, arg2):
...             return arg1 + arg2
...


该修饰符用在类内部的函数上

静态方法,是不依赖类的实例的方法,其方法的第一个参数不是类的实例(对象)。

有两种调用方式:

直接通过类来调用

通过类的实例来调用(此时静态方法无视类的实例的存在)

调用
ClassD
的静态方法
,如下:

>>> ClassD.func(1,2)     # 通过类直接调用即可
3
>>> ClassD().func(1,2)   # 通过实例来调用,func无视实例的存在,即会忽略实例
3


对于静态方法来说,其类型总是function。因为静态方法是不用依赖类的实例(对象)的。

>>> type(ClassD.funC)
<class 'function'>
>>> type(ClassD().funC)
<class 'function'>


关于staticmethod的官方说明:https://docs.python.org/3/library/functions.html#staticmethod

★ 4. 参考

Python中Function(函数)和method(方法): http://blog.csdn.net/lastinglate/article/details/7295248

Python里method和function的区别: http://blog.csdn.net/peachpi/article/details/6047826

关于Python的函数(Method)与方法(Function): https://www.cnblogs.com/blackmatrix/p/6847313.html

Difference between a method and a function:

https://stackoverflow.com/questions/155609/difference-between-a-method-and-a-function

https://stackoverflow.com/questions/20981789/difference-between-methods-and-functions

Built-in Functions: https://docs.python.org/3/library/functions.html

Google Python Style Guide中的命名规则:https://google.github.io/styleguide/pyguide.html?showone=Naming#Naming

Python 风格指南(Google Python Style Guide中文版): http://zh-google-styleguide.readthedocs.io/en/latest/google-python-styleguide/contents/

关于python中protected和private的解释:https://stackoverflow.com/questions/20261517/inheritance-of-private-and-protected-methods-in-python

python中protected和private的函数,都是可以被外部调用的。他们与public的区别有:

help(ClassName)时,public的函数是可见的,protected和private的函数不可见

调用时,protected的函数与public函数调用一样,但是private函数需要通过
_类名<函数名>
来调用。例如一个类
MyClass
有一个私有函数
__my_private_func()
,调用时要用
_MyClass__my_private_func()
(加上下划线和类名)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: