python创建类实例方法_Python 如何通过类方法创建实例方法?

news/2024/7/6 1:49:03

下面是 Python 3.x language reference 中的一段话,大意是理解的,不过写不出一个这样的示例,求大神给个与这段话一致的示例:

When an instance method object is derived from a class method object, the “class instance” stored in self will actually be the class itself, so that calling either x.f(1) or C.f(1) is equivalent to calling f(C,1) where f is the underlying function.

其實這個部分,你自己做做實驗就會明白。

我們從原文開始看起,分成兩段來討論,第一段說道:

When an instance method object is called, the underlying function (__func__) is called, inserting the class instance (__self__) in front of the argument list. For instance, when C is a class which contains a definition for a function f(), and x is an instance of C, calling x.f(1) is equivalent to calling C.f(x, 1).

原文第一段說,當一個

instance method object

被調用時,

__func__

的第一個參數先代入

class instance

後被調用,接著舉了一個例子:

x.f(1) == C.f(x,1)  # x is an instance of C

我們用下面的範例來說明,在這裡我們有一個類

Demo

,他底下有一個 function

foo

和 function

bar

Demo

類:

class Demo:

def foo(self, *args):

return 'Call foo by instance' + repr(self) + 'with args' + repr(args)

@classmethod

def bar(cls, *args):

return 'Call bar by class ' + repr(cls) + 'with args' + repr(args)

實際上呢:

Python 對於

foo

,會產生一個 一般的 function,這個 function 會被

Demo.foo

所參考。

當我們寫出

demo.foo

的時候,Python 會即時創造一個 bound method object:

demo.foo

,這個 method object 是個綁定的 method,綁定甚麼呢? 當然就是綁定

demo

這個 instance,所以

demo.foo.__self__

會參考到

demo

, 同時 Python 也會把

Demo.foo

記在

demo.foo.__func__

中。

所以當這個

demo.foo

被呼叫的時候(

demo.foo(1,2,3)

),他其實會去呼叫

demo.foo.__func__

,並且以

demo.foo.__self__

(其實也就是

demo

自己) 當作第一個參數。

以我們寫的類來展示的話,他的例子變成:

x.f(1)   ==    C.f(x, 1)

demo.foo(1) == Demo.foo(demo, 1) == demo.foo.__func__(demo.foo.__self__, 1)

看看代碼:

demo  = Demo()

print('=== Demo start ===\n')

print('demo.foo', ':', demo.foo)

print('    [type             ] ', type(demo.foo))

print('    [demo.foo.__self__] ', demo.foo.__self__)

print('    [demo.foo.__func__] ', demo.foo.__func__)

print('    [demo.foo(1,2,3)  ] ', demo.foo(1,2,3))

print()

print('Demo.foo', ':', Demo.foo)

print('    [type                 ] ', type(Demo.foo))

print('    [Demo.foo(demo, 1,2,3)] ', Demo.foo(demo, 1,2,3))

print()

print('demo.foo.__func__', ':',  demo.foo.__func__,)

print('    [type                          ] ', type(demo.foo.__func__))

print('    [demo.foo.__func__(demo, 1,2,3)] ', demo.foo.__func__(demo, 1,2,3))

print()

print('Demo.foo is demo.foo.__func__ --> ', Demo.foo is demo.foo.__func__)

測試結果:

=== Demo start ===

demo.foo : <bound method Demo.foo of <__main__.Demo object at 0x7f413db47fd0>>

[type             ]  <class 'method'>

[demo.foo.__self__]  <__main__.Demo object at 0x7f413db47fd0>

[demo.foo.__func__]  <function Demo.foo at 0x7f413db41840>

[demo.foo(1,2,3)  ]  Call foo by instance<__main__.Demo object at 0x7f413db47fd0>with args(1, 2, 3)

Demo.foo : <function Demo.foo at 0x7f413db41840>

[type                 ]  <class 'function'>

[Demo.foo(demo, 1,2,3)]  Call foo by instance<__main__.Demo object at 0x7f413db47fd0>with args(1, 2, 3)

demo.foo.__func__ : <function Demo.foo at 0x7f413db41840>

[type                          ]  <class 'function'>

[demo.foo.__func__(demo, 1,2,3)]  Call foo by instance<__main__.Demo object at 0x7f413db47fd0>with args(1, 2, 3)

Demo.foo is demo.foo.__func__ -->  True

接著看第二段:

When an instance method object is derived from a class method object, the “class instance” stored in self will actually be the class itself, so that calling either x.f(1) or C.f(1) is equivalent to calling f(C,1) where f is the underlying function.

第二段的大意是說,當 instance method object 是來自於 class method object 的時候,存在

self

裡的 類實例 會是 類 本身,之後又舉了一個例子:

x.f(1) == C.f(1) == f(C,1)  # x is an instance of C

我們一樣用範例來說明:

Python 對於 bar, 會產生

Demo.bar

,他是一個來自於 class method object 的 bound method object,原本

Demo.bar

就跟

Demo.foo

一樣是個一般的 Python function,但是透過修飾器(

@classmethod

修飾器),他成為了一個 bound method object,若要觀察原本的 general function,只能在

Demo.bar.__func__

中看到,同時他綁定了

Demo

類,所以

Demo.bar.__self__

會參考到

Demo

類。

所以當

Demo.bar

被呼叫的時候(

Demo.bar(1)

),,他其實會去呼叫

Demo.bar.__func__

,並且以

Demo.bar.__self__

(其實也就是

Demo

自己) 當作第一個參數。

以我們寫的類來展示的話,他的例子變成:

x.f(1)   ==    C.f(1)   == f(C, 1)

demo.bar(1) == Demo.bar(1) == Demo.bar.__func__(Demo, 1) == Demo.bar.__func__(Demo.bar.__self__, 1)

測試代碼:

demo  = Demo()

print('=== Demo start ===\n')

print('Demo.bar', ':', Demo.bar)

print('    [type             ] ', type(Demo.bar))

print('    [Demo.bar.__self__] ', Demo.bar.__self__)

print('    [Demo.bar.__func__] ', Demo.bar.__func__)

print('    [Demo.bar(1,2,3)  ] ', Demo.bar(1,2,3))

print()

print('Demo.bar(1)               ', Demo.bar(1))

print('demo.bar(1)               ', demo.bar(1))

print('Demo.bar.__func__(Demo, 1)', Demo.bar.__func__(Demo, 1))

測試結果:

=== Demo start ===

Demo.bar : <bound method type.bar of <class '__main__.Demo'>>

[type             ]  <class 'method'>

[Demo.bar.__self__]  <class '__main__.Demo'>

[Demo.bar.__func__]  <function Demo.bar at 0x7f413db41950>

[Demo.bar(1,2,3)  ]  Call bar by class <class '__main__.Demo'>with args(1, 2, 3)

Demo.bar(1)                Call bar by class <class '__main__.Demo'>with args(1,)

demo.bar(1)                Call bar by class <class '__main__.Demo'>with args(1,)

Demo.bar.__func__(Demo, 1) Call bar by class <class '__main__.Demo'>with args(1,)

結論:

在 Python3 中,class 內有兩種 funciton,一種是一般的 function object,另外一種是 bound method object

instance method 是一般的 function 綁定了 instance 所構成的 method object,class mehtod 是一般的 function 綁定了 class 所構成的 method object

bound method 被調用的時候,其實都是調用最原始的 function (記在

__func__

中),但會以綁定的對象作為第一個參數(記在

__self__

中)。

參考資料:

Difference between methods and functions

Different way to create an instance method object in Python

# -*- coding: utf-8 -*-

class Parent:

@classmethod

# 这里就相当于是f

def foo(cls, arg):

print("foo called, " + str(cls) + " " + str(arg))

class Child(Parent):

pass

# 创建一个子类的实例

a = Child()

# 调用类方法,可见将对象传递给类方法时,会调用类方法,并且自动绑定了类

a.foo(1)

# 结果和上述一样

Child.foo(1)


http://www.niftyadmin.cn/n/3003986.html

相关文章

JVM虚拟机(二):堆、栈、方法区概念区别

Java 堆 Java堆是和Java应用程序关系最密切的内存空间&#xff0c;几乎所有的对象都放在其中&#xff0c;并且Java堆完全是自动化管理&#xff0c;通过垃圾收集机制&#xff0c;垃圾对象会自动清理&#xff0c;不需自己去释放。 根据垃圾回收机制的不同&#xff0c;Java堆有可能…

各路由协议的协议号_2020春节档,各路高手巅峰对决?鹿死谁手

《宠爱》12月31日上映&#xff0c;元旦期间连续两天票房破亿&#xff0c;电影的热度是近期新上映的电影中最高的一部。《宠爱》在豆瓣开画评分仅6.3&#xff0c;所以说档期选的好&#xff0c;容易出爆款&#xff1b;那么大年初一的上映的各路高手将迎来巅峰对决&#xff0c;那么…

http响应报文,如果响应的内容比较大,客户端怎么样判断接收完了呢?

1. http协议有正文大小说明的content-length2. 或者分块传输chunked的话 读到0\r\n\r\n 就是读完了 ----------------------------------------------------------------------------------------------- http响应内容比较大的话&#xff0c;会分成多个tcp segment 发送&am…

ni软件可以卸载吗_你的软件真的全部卸载干净了吗?最高效软件卸载工具推荐...

▌ 前言我们在电脑上运行 .exe 软件安装包时&#xff0c;安装程序会生成一些程序文件、后台服务和注册表项等&#xff0c;用以支持软件的正常运行。但是&#xff0c;在卸载软件时&#xff0c;很多软件的卸载程序并不能完全清除安装文件&#xff0c;经常卸载不干净&#xff0c;残…

springboot全局的异常拦截处理

1 全局异常处理与HttpServletResponse响应 RestControllerAdvice是帮助我们把信息转成json格式返回 ResponseBody是将方法中的字符串转成json格式同一返回&#xff0c;一般该方法返回值为Object 1.1 使用RestControllerAdvice搭配ExceptionHandler&#xff08;推荐&#xff0…

菜鸡互啄队—— 团队合作

团队GitHub地址&#xff1a;https://github.com/BigBugWriters/pit 队名&#xff1a; 菜鸡互啄 队员学号&#xff1a; 姓名学号梁华超&#xff08;队长&#xff09;3116005144沈春霖3116005153杨钊雄3116005160林健城3116005145林奇凯3116005146林贤杰3116005147拟作的团队项目…

Springboot使用Aop拦截器记录方法运行总时长

写了一个方法&#xff0c;感觉逻辑又臭又长&#xff0c;想知道该方法的执行时间&#xff0c;于是写了一个拦截器&#xff0c;获取service中的每个方法的执行时间&#xff0c;查看其响应时长。 第一部分与第二部分转载自大佬的博客&#xff1a;https://blog.csdn.net/mu_wind/a…

java使用POI操作XWPFDocument中的XWPFRun(文本)对象的属性详解

转载自 https://www.cnblogs.com/libin6505/p/10338765.html 我用的是office word 2016版 XWPFRun是XWPFDocument中的一段文本对象&#xff08;就是一段文字&#xff09; 创建文档对象 XWPFDocument docxDocument new XWPFDocument(); 创建段落对象 XWPFParagraph parag…