ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Python学习笔记——类和对象(如何定义一个类并创建对象、魔法方法、__init__、__repr__)

2021-10-23 20:29:59  阅读:116  来源: 互联网

标签:__ val Python self 创建对象 对象 init 方法


面向对象的编程语言?

Python到底是一种什么类型的编程语言:面向对象、函数式还是过程式语言?
Python借用了所有这3种流行方法的编程范式,还鼓励程序员根据需要混合使用

在其他编程语言中(如Java)你写的所有代码都必须放在一个类里,要从这个类实例化对象
在Python中,可以用你熟悉的任何一种范式创建代码,可以同样把所有代码放在一个类中,也可以不这么做

Python支持面向对象编程(OOP):如封装一个对象、继承和多态

Python的类

  • 类将行为(本质即函数)和状态(本质即变量)打包在一个对象中
  • Python中的类相当于JS中的原型,类可以完成对象实例化(从类可以创建新的对象实例)
  • 对象共享行为,但不共享状态
    从一个类创建对象时,每个对象会共享这个类的行为(类中定义的方法),但是会维护其自己的状态副本(属性)

为类增加方法:直接在类中定义函数即可
为类增加属性:在__init__中完成

定义一个类,并创建对象

定义一个CountFromBy类,从这个类能创建如下的对象:

  • 属性:具有初始值val和步长incr(若没有指定,默认val为0,incr为1)
  • 方法:具有increase()方法,每次调用时对象的属性val增加incr

1. 为类增加方法

  • 要为类增加方法,直接在类中使用def定义函数即可
  • 注意,Python类的任何方法必须传入第一个参数,用来指示当前对象,即当前正在使用此方法的对象
    Python编程社区约定的做法是:总是将方法的第一个参数命名为self(类似于JS中的this
  • 在方法代码组中,引用属性时要加self前缀,确保操作应用于对象的属性。
    如下,应该写self.val而不是val
    前面说过对象共享行为,但不共享状态,只有这样才知道在方法中要修改哪一个对象的属性(即当前正在使用方法的那个对象)
    另外,这样做能保证调用结束后,变量仍存在:如果只写val,则调用结束后变量被销毁,无法再访问val(超出作用域),而对象中的val属性没有发生改变
class CountFromBy:#约定:对于类,采用CamelCase命名
    def increase(self) -> None:
        self.val += self.incr
    ...
    ...

如何调用方法

根据上文,已经知道Python对象调用方法时,第一个参数一定传入这个对象的引用
那么,对于CountFromBy类的a实例,我们调用increase方法时,应该这样写:

>>>a = CountFromBy(0,1)
>>>CountFromBy.increase(a)#调用类的一个方法,传入的第一个参数是某个对象实例

然而实际的写法为

>>>a = CountFromBy(0,1)
>>>a.increase()

实际上,解释器会自动将a.increase()语句转化为CountFromBy.increase(a)语句

因此我们只要使用a.increase()的简单版本就好

  • 这时要明白,我们调用increase方法时,需要提供的参数就少一个
    因为在调用方法时,解释器自动将当前对象a赋给第一个参数self

2. 从类创建对象实例时,初始化对象的属性

创建一个新对象时,如何初始化呢?
如果你了解面向对象编程,肯定会想到在其他语言中的“构造函数”。
构造函数是一个特殊方法,它定义了第一次创建一个对象时会发生什么(包括对象实例化和属性初始化)

在JS中使用构造函数:

//Dog称为构造函数

function Dog(name, breed, weight) {
	//“对象实例化”部分(将传入的参数赋给新对象的属性)
	this.name = name;
	this.breed = breed;
	this.weight = weight;
}
Dog.prototype.run = function() {
	console.log("Run!"); 
};
//“属性初始化”部分
Dog.prototype.name = "dog";
Dog.prototype.breed = "unknown";
Dog.prototype.weight= 0;

//传入参数,获得一个具有某些属性的对象
var fido = new Dog("Fido", "Mixed", 38);

在 Python中有所不同:

  • 对象实例化由解释器自动处理,所以不需要定义构造函数来完成这个工作
  • 属性初始化的工作需要自己完成:有一个名为__init__(称为dunder init)的魔法方法允许你根据需要初始化属性。

绕路介绍一下前置知识:魔法方法__init__(dunder init)

  • object类是Python解释器内置的类
  • Python中所有类都自动继承这个类(包括你自定义的类)
    这意味着,所有类都继承了object类的标准行为(即一些方法),当然也可以根据需要覆盖它们(提供你自己的方法实现)
  • object中的标准方法中,若其名称包含双下划线dunder__,称为魔法方法
    在自己的类中,覆盖这些魔法方法(编写自己的代码)通常很有用
    覆盖__eq__方法,可指定从类创建的对象使用相等操作符==时会发生什么
    覆盖__ge__方法,可指定对对象使用大于操作符>时要发生什么
    覆盖__init__方法,可指定要如何初始化对象属性
    覆盖__repr__方法,可指定解释器要如何表示对象

使用__init__初始化对象的属性

从 Python类创建的新对象,如何初始化呢?

在你的类中覆盖(重新定义)__init__方法即可

  • 每次从你的类创建一个新对象时,解释器都会调用你的__init__方法
  • 传入类的参数值,会被发送到__init__
    例如,对于mycount=CountFromBy(100,10),100和10会被传入__init__

ps.__init__同样是一个方法,也要遵循前述规则:必须有第一个参数self

class CountFromBy:
    def __init__(self,v: int=0, i: int=1) -> None:
    #v默认值为0,i默认值为1
        self.val = v
        self.incr = i
    def increase(self) -> None:
        self.val += self.incr

3. 创建并使用对象

已经为类增加了方法、初始化了属性
下面就可以从类创建对象了

>>> a=CountFromBy()#使用默认值val=0,incr=1
>>> a.increase()
>>> a.val
1

>>> b=CountFromBy(100,10)#指定属性val=100,incr=10
>>> b.increase()
>>> b.val
110

额外介绍一个魔法方法:__repr__

直接打印“对象”,会显示什么呢?

>>> c=CountFromBy()
>>> c
<__main__.CountFromBy object at 0x000002BE66000A90>

>>> type(c)
<class '__main__.CountFromBy'>
>>> hex(id(c))
'0x2be66000a90'

解释器默认表示对象的方式是:对象类型+内存地址

编写自己的魔法方法__repr__,可以覆盖这种默认行为,并指定解释器对于对象的字符串表示

class CountFromBy:
    def __init__(self,v: int=0, i: int=1) -> None:
        self.val = v
        self.incr = i
    def increase(self) -> None:
        self.val += self.incr
    def __repr__(self) -> str:
        return str(self.val)
        
================= RESTART: C:\Users\13272\Desktop\CountFb.py =================
>>> c=CountFromBy(100,10)
>>> c.val
100

>>> c
100#自定义的对象表示方法

标签:__,val,Python,self,创建对象,对象,init,方法
来源: https://blog.csdn.net/Insomnia_X/article/details/120889404

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有