在python中function啥类型_Python中function和method

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

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

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

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

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

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

Type

Public

Internal

解释

Functions

lower_with_under()

_lower_with_under()

如果允许外部模块调用,命名采用小写字母加下划线(不以下划线开头)。

如果不允许外部调用,则命名以下划线开头,表示私有。

Method Names

lower_with_under()

_lower_with_under() (protected) or __lower_with_under() (private)

如果对外公开(外部可调用),则命名为小写字母加下划线,且不以下划线开头。

如果不对外公开,命名以一个下划线开头(protected)或者以以2个下划线开头(private)。注意:这里的protected和private与C++中的访问策略不一样。python中所谓的protected和private函数都是可以被调用的。更多内容,请见『参考』

Function/Method Parameters

lower_with_under

function或者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 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)

>>> type(ClassB().funcB)

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

>>>type(ClassC.func)

# 注意,这里不是function类型

>>>type(ClassC().func)

★ 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)

>>> type(ClassE().funcE)

看看classmethod的第一个参数:

>>> class ClassE(object):

... @classmethod

... def funcE(cls, arg1, arg2):

... print(cls)

... return arg1 + arg2

...

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

>>> ClassE.funcE(1,2)

3

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

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'

★ 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)

>>> type(ClassD().funC)

★ 4. 参考

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

调用时,protected的函数与public函数调用一样,但是private函数需要通过_类名来调用。例如一个类MyClass有一个私有函数__my_private_func(),调用时要用_MyClass__my_private_func()(加上下划线和类名)。

Python使用MD5时出现'builtin_function_or_method' object has no attribute错误的原因通常是因为命名冲突或使用方式不正确。下面是一些可能导致这个错误的常见问题和解决方法: 1. 导入错误:首先,请确保正确导入了 hashlib 模块。在使用 MD5 之前,需要通过 `import hashlib` 来导入 hashlib 模块。如果没有正确导入 hashlib,就无法使用 hashlib.md5() 函数,而可能会出现上述错误。 2. 命名冲突:如果你在代码使用了名为 `hashlib` 的变量名或函数名,将会导致冲突。例如,如果你的代码有 `hashlib = 'something'` 这样的语句,那么后续使用 hashlib.md5() 时会出现错误。解决方法是重新命名该变量,或者重新加载模块。 3. 使用方式错误:正确使用 hashlib.md5() 函数的方式是创建一个 hashlib.md5() 对象,然后将要加密的数据通过调用对象的 `update()` 方法传递进去,最后调用 `hexdigest()` 方法获取加密结果。示例代码如下: ```python import hashlib data = '要加密的数据' md5_obj = hashlib.md5() md5_obj.update(data.encode()) # update() 方法需要传入字节类型的数据,所以需要使用 encode() 方法将字符串转为字节 result = md5_obj.hexdigest() print(result) ``` 以上是关于'builtin_function_or_method' object has no attribute错误的一些常见原因和解决方法。根据具体情况,你可以检查导入是否正确、命名是否冲突以及使用方式是否正确来解决这个问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值