LOADING...
LOADING...
LOADING...
当前位置: 玩币族首页 > 新闻观点 > 开启Python学习之路

开启Python学习之路

2020-05-13 盘古私募量化孵化 来源:区块链网络

一、类

提示: 从 概念 逻辑 应用场景 语法来分别讲解, “流水仗”, “金字塔结构化思维”, “模板抽象”

面向对象(OOP)基本概念

面向对象编程 —— Object Oriented Programming 简写 OOP

1.1.1 面向对象基本概念

? 面相过程 和 面相对象,是两种不同的 编程方式

? 对比面向过程 的特点,可以更好地了解什么是 面向对象

1.1.2 过程和函数(科普)

? 过程是早期的一个编程概念

? 过程类似于函数,只能执行,但是没有返回值

? 函数不仅能执行,还可以返回结果

1.1.3 面向过程 和 面向对象 基本概念

1.面向过程

? 把完成某一个需求的 所有步骤 头到尾 逐步实现

? 根据开发需求,将某些 功能独立 的代码 封装 成一个又一个 函数

? 最后完成的代码,就是顺序地调用 不同的函数

特点:

? 注重步骤与过程,不注重职责分工

? 如果需求复杂,代码会变得很复杂

? 开发复杂项目,没有固定的套路,开发难度很大!

面向对象

面向对象 是 更大 的 封装,根据 职责 在 一个对象中 封装 多个方法

1.在完成某一个需求前,首先确定 职责 —— 要做的事情(方法)

2.根据 职责 确定不同的 对象,在 对象 内部封装不同的 方法(多个)

3.顺序地让 不同的对象 调用 不同的方法

特点

? 注重 对象和职责,不同的对象承担不同的职责

? 更加适合应对复杂的需求变化,是专门应对复杂项目开发,提供的固定套路

? 需要在面向过程基础上,再学习一些面向对象的语法

面向对象三大特征

封装

? 封装 是面向对象编程的一大特点

? 面向对象编程的 第一步 —— 将 属性 和 方法 封装 到一个抽象的 类 中

? 外界 使用 类 创建 对象,然后 让对象调用方法

? 对象方法的细节 都被 封装 在 类的内部

继承

? 实现代码的重用,相同的代码不需要重复的编写

多态

? 不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度

二. 类和对象

类 和 对象 是 面向对象编程的 两个 核心概念

2.1.1 类

1.类 是对一群具有 相同 特征 或者 行为 的事物的一个统称,是抽象的,不能直接使用

类 就相当于制造航空母舰时的图纸,是一个 模板,是 负责创建对象的

2.特征 被称为 属性

3.行为 被称为 方法

案例演练: 根据下面的描述来实现 类 属性 和 方法 的提取

?李雷?今年?18?岁,身高?1.75,每天早上?跑?完步,会去?吃?东西 ?韩梅梅?今年?17?岁,身高?1.65,韩梅梅不跑步,韩梅梅喜欢?吃?东西

2.1.2 对象

对象 是 由类创建出来的一个具体 实例 ,可以直接使用.

? 由哪一个类创建的对象, 就拥有在 哪一个类中定义的 属性 和 方法

? 类(抽象: 模板) --> 对象(具体: 实例) 过程: 实例化

2.1.3 类和对象的关系

? 类是模板,对象 是根据 类 这个模板创建出来的,应该 先有类,再有对象

? 类 只有一个,而 对象 可以有很多个

? 不同的对象 之间 属性 可能会各不相同

? 类 中定义了什么 属性和方法,对象 中就有什么属性和方法,不可能多,也不可能少

2.1.4 类的设计

类名 : 大驼峰, “见名知义”

? 名词提炼法 分析 整个业务流程,出现的 名词,通常就是找到的类

? 属性 (静态): 对象的特征描述

? 方法 (动态) : 对象具有的行为(动词)

提示:需求中没有涉及的属性或者方法在设计类时,不需要考虑

2.1.5 查看: 类具有的属性和方法

1.python的内置函数(BIF): dir() , 注: 括号内传入 标识符

2.在交互式或者IDE的情况下, 在 对象的标识符 后继续输入. , 然后再按 Tab键 会提示 该标识符所具有的属性和方法

2.1.6 python自己提供的常见的内置属性和类方法

方法名 类型 作用

new 方法 创建对象的时候, 会被自动调用, 给对象分配内存地址和空间

init 方法 对象被初始化时, 会被自动调用

del 方法 对象被从内存中销毁前, 会被自动调用

str 方法 返回对象的描述信息, print函数输出使用

2.1.7 定义类的实例方法语法和注意事项

class?DefineClass: ????"""定义一个只包含实例方法的类""" ????def?func1(self,?*args,?**kwargs): ????????pass ????def?func2(self,?*args,?**kwargs): ????????pass

注意事项:

? 方法 定义格式和之前的函数几乎相同, 唯一的区别是, 对象的方法第一个参数必须是 self

? 注: 当然也不必须是self, 但是 self 已经是约定俗成的; 可以当作必须是 self

? self 代表什么含义呢?

哪一个对象调用的 的方法, self 就是哪一个对象的引用

类名命名: 大驼峰

2.1.8 创建对象的语法

对象变量 = 类名()

2.1.9 案例演练

上述的需求扩展成具体的代码

class?Person: ????def?__init__(self,?name,?age,?height): ????????self.name?=?name ????????self.age?=?age ????????self.height?=?height ???????? ????def?eat(self): ????????print("%s?贪吃"?%?self.name) ???????? ????def?run(self): ????????print("%s?去跑步"?%?self.name) #?语法规范:?方法之间空1个行

lilei?=?Person('lilei',?18,?175.5) #?addr?=?id(lilei) #?print("%d"?%?addr) print(Person) print(lilei) print(lilei.name)

hanmeimei?=?Person('hanmeimei',?17,?165) print(Person) print(hanmeimei) print(hanmeimei.name)

#?lilei?=?Person('lilei',?18,?175.5) #?print(lilei) #?print(lilei.name)

#?给实例对象添加属性 lilei.weight?=?56

12.1.10 python 的 “引用” 概念(强调)

在面向对象开发中,引用的概念是同样适用的!

? 在 Python 中使用类 创建对象之后,实例对象变量中 仍然记录的是 对象在内存中的地址

也就是变量 引用 了 实例化后的实例对象

? 使用 print 输出 对象变量,默认情况下,是能够输出这个变量 引用的对象 是 由哪一个类创建的对象,以及 在内存中的地址(十六进制表示)

提示:在计算机中,通常使用 十六进制 表示 内存地址

十进制 和 十六进制 都是用来表达数字的,只是表示的方式不一样

十进制 和 十六进制 的数字之间可以来回转换

%d 可以以 10 进制 输出数字

%x 可以以 16 进制 输出数字

2.1.11 self 参数

#?需求分析: """ 1.?某人的一天 2.?属性: 姓名, 身高, 体重。。。 3.?方法: 跑步, 吃饭 。。。 4.?实现一个只有方法的类 """

class?Person: ????"""某人的一天""" ????def?run(self): ????????print("%s爱跑步"?%?self.name)

def?eat(self): ????????print("周老师爱吃面")

#?类的使用第一步:?实例化 person?=?Person()??#?实例化并赋值给person变量 print(Person.__doc__) print(Person())??#?实例化 print(person)??#?打印第一次实例化的对象

#?给对象定义属性 person.name?=?"周老师"

#?调用实例对象的方法 BL.INK?-?Login() #?BL.INK?-?Login()??#?报错:?实例出的新对象

print(dir(Person))

由 哪一个对象 调用的方法,方法内的 self 就是 哪一个对象的引用

? 在类封装的方法内部,self 就表示 当前调用方法的对象自己

? 调用方法时,程序员不需要传递 self 参数

? 在方法内部

可以通过 self. 访问对象的属性

也可以通过 self. 调用其他的对象方法

? 在 类的外部,通过 变量名. 访问对象的 属性和方法

? 在 类封装的方法中,通过 self. 访问对象的 属性和方法

解决上面的"弊端", Python专门提供了 init 方法.

提示

在日常开发中,不推荐在类的外部给对象增加属性

? 如果在运行时,没有找到属性,程序会报错

对象应该包含有哪些属性,应该 封装在类的内部

需求分析:

“”"

某人的一天

属性: 姓名, 身高, 体重。。。

方法: 跑步, 吃饭 。。。

实现一个只有方法的类

“”"

class Person:

“”“某人的一天”""

def?__init__(self,?name,?height,?weight): ??????self.name?=?name ??????self.height?=?height ??????self.weight?=?weight

def?run(self): ??????print("%s爱跑步"?%?self.name)

def?eat(self): ??????print("周老师爱吃面")

def?__str__(self): ??????return?"这是一个展示实例对象人性化提示的方法"

def?__del__(self): ??????print("这是__del__方法")

#?def?get_weight(self): ??#?????return?199

类的使用第一步: 实例化

person = Person(“周老师”, 188, 56) # 实例化并赋值给person变量

BL.INK - Login()

print(person)

print(dir(person))

print(person.weight)

del perso

print("*" * 50)

2.1.12 初始化方法的具体介绍

? 当使用类名()创建对象时,会自动执行以下操作:

为对象在内存中 分配空间 —— 创建对象方法(new)

为对象的属性 设置初始值 —— 初始化方法(init)

? 这个 初始化方法 就是 init 方法,init 是对象的内置方法

? init 方法是 专门 用来定义一个实例对象 具有哪些属性的方法!

在 init 方法内部使用 self.属性名 = 属性的初始值 就可以 定义属性

定义属性之后,再使用 类创建的对象,都会拥有该属性

具体操作:

把希望设置的属性值,定义成 init 方法的参

在方法内部使用 self.属性 = 形参 接收外部传递的参数

在创建对象时,使用 类名(属性1, 属性2…) 调用

“”"

1.有一个mysql客户端

2.连接mysql需要 ip地址 port端口号 数据库名 用户名 密码

3.通过mysql客户端操作mysql数据库, 插入一条数据到数据库中的某个表中

5.关闭mysql客户端数据库连接

6.智能提示mysql客户端信息

“”"

class MysqlClient:

“”“mysql客户端类”""

def init(self, ip, port, db_name, user_name, user_passwd):

self.ip = ip

self.port = port

self.db_name = db_name

self.user_name = user_name

self.user_passwd = user_passwd

def?insert_data(self,?data): ?????"""插入数据到mysql数据库""" ?????print("插入%s到mysql数据了。。。"?%?data)

def?__del__(self): ?????print("我已经执行了") ?????return?"发送close信号"

def?__str__(self): ?????return?"这是我们自定义的mysql客户端操作方法

mysql_client = MysqlClient(“127.0.0.1”, 3306, “db_name”, “root”, “password”)

mysql_client.insert_data(“有用教育”)

print(mysql_client)

2.1.13 其他内置方法和属性

del 方法

在 Python 中

? 当使用 类名() 创建对象时,为对象 分配完空间后,自动 调用 __init__方法

? 当一个 对象被从内存中销毁 前,会 自动 调用 del 方法

生命周期

? 一个对象从调用 类名() 创建,生命周期开始

? 一个对象的 del 方法一旦被调用,生命周期结束

? 在对象的生命周期内,可以访问对象属性,或者让对象调用方法

str 方法

? 在 Python 中,使用 print 输出 对象变量,默认情况下,会输出这个变量 引用的对象 是 由哪一个类创建的对象,以及 在内存中的地址(十六进制表示)

? 如果在开发中,希望使用 print 输出 对象变量 时,能够打印 自定义的内容,就可以利用 str 这个内置方法了

? 注意:str 方法必须返回一个字符串

2.2.1 封装案例

""" 案例2: 知识点:?一个对象的属性可以是?另外一个类创建的对象

1.?周老师?有一个?存钱罐(型号,?容量) 2.?周老师?可以?花钱 3.?存钱罐?可以?提供?钱?给周老师去花 4.?存钱罐?可以?提供?位置?给周老师藏钱

"""

""" 技术方案: 1.定义一个存钱罐类 2.存钱罐类有两个方法:?“吃钱”,?“吐钱” 3.存钱罐类要有两个属性:型号, 容量

4.定义一个人类 5.人类有属性:?周老师 6.人类有方法:?花钱,?存钱

--------- 问题: 1.我们应该先定义什么类?? 2.分析之后发现还需要?给?存钱罐?添加属性?剩余容量 3.分析之后发现还需要?给?人类?添加属性?存钱罐 4.分析之后发现?存钱?可以不写

"""

class?Piggy: ????""" ????这是一个存钱罐类 ????存钱罐类有两个方法:?“吃钱”,?“吐钱” ????存钱罐类要有两个属性:型号, 容量 ????""" ????def?__init__(self,?cate,?total_money): ????????self.cate?=?cate ????????self.money?=?total_money ????????self.remain_money?=?total_money

def?eat_money(self,?money): ????????"""吃钱""" ????????if?money?>?self.remain_money: ????????????print("待放入的钱已经超过容量,?容量剩余{}".format(self.remain_money)) ????????????return ????????else: ????????????#?self.remain_money?=?self.remain_money?-?money ????????????self.remain_money?-=?money ????????????print("本次存入%s,?还剩余容量:?%s"?%?(money,?self.remain_money))

def?out_money(self): ????????"""吐钱,?每次出1万""" ????????if?self.money?-?self.remain_money?<?1: ????????????print("余额{}不足,?请充值".format(self.money?-?self.remain_money)) ????????else: ????????????self.remain_money?+=?1 ????????????print("还剩余钱数:?%s"?%?(self.money?-?self.remain_money))

class?Person: ????"""人类""" ????def?__init__(self,?name): ????????self.name?=?name ????????self.piggy?=?None

def?spend_money(self): ????????"""花钱""" ????????#?重点:花钱之前需要判断是否有实例化的存钱罐 ????????if?self.piggy?is?None: ????????????print("%s?还没有放私房钱的地方"?%?self.name) ????????????return ????????else: ????????????self.piggy.out_money()

piggy?=?Piggy("小猪佩奇",?20) person?=?Person("周老师") person.spend_money()

piggy.eat_money(2) person.spend_money()

piggy.eat_money(200)

小结

1.创建了一个 人类,使用到 init 内置方法

2.在定义属性时,如果 不知道设置什么初始值,可以设置为 None

3.在 封装的 方法内部,还可以让 自己的 使用其他类创建的对象属性 调用已经 封装好的方法 如self.piggy.out_money()

补充

1.定义没有初始值的属性

在定义属性时,如果 不知道设置什么初始值,可以设置为 None

? None 关键字 表示 什么都没有

? 表示一个 空对象,没有方法和属性,是一个特殊的常量

? 可以将 None 赋值给任何一个变量

2.身份运算符

身份运算符用于 比较 两个对象的 内存地址 是否一致 —— 是否是对同一个对象的引用

在 Python 中针对 None 比较时,建议使用 is 判断

运算符 描述 实例

is is 是判断两个标识符是不是引用同一个对象 x is y,类似 id(x) == id(y)

is not is not 是判断两个标识符是不是引用不同对象 x is not y,类似 id(a) != id(b)

is 与 == 区别:

is 用于判断 两个变量 引用对象是否为同一

== 用于判断 引用变量的值 是否相等

>>>?a?=?[1,?2,?3] >>>?b?=?[1,?2,?3] >>>?b?is?a? False >>>?b?==?a True

2.2.2 私有属性和私有方法

1.应用场景

? 在实际开发中,对象 的 某些属性或方法 可能只希望 在对象的内部被使用,而 不希望在外部被访问到

? 私有属性 就是 对象 不希望公开的 属性

? 私有方法 就是 对象 不希望公开的 方法

2.定义方式

在 定义属性或方法时,在 属性名或者方法名前 增加 两个下划线,定义的就是 私有 属性或方法

案例演练

class Women:

def?__init__(self,?name):

self.name?=?name ?????#?不要问女生的年龄 ?????self.__age?=?18

def?__secret(self): ?????print("我的年龄是?%d"?%?self.__age)

xiaofang = Women(“小芳”)

私有属性,外部不能直接访问

print(xiaofang.__age)

私有方法,外部不能直接调用

xiaofang.__secret()

4.伪私有属性和私有方法

提示:在日常开发中,不要使用这种方式,访问对象的 私有属性 或 私有方法

Python 中,并没有 真正意义 的 私有

在给 属性、方法 命名时,实际是对 名称 做了一些特殊处理,使得外界无法访问到

处理方式:在 名称 前面加上 _类名 => _类名__名称

-----------------(接上面的案例)-----------------

私有属性,外部不能直接访问到

print(xiaofang._Women__age)

私有方法,外部不能直接调用

xiaofang._Women__secret()

2.3.1 继承(单继承)

面向对象三大特性

封装 根据 职责 将 属性 和 方法 封装 到一个抽象的 类 中

继承 实现代码的重用,相同的代码不需要重复的编写

多态 不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度

单继承: 继承的概念、语法和特点

继承的概念:子类 拥有 父类 的所有 方法 和 属性

继承的语法

class 类名(父类名):

pass

? 子类 继承自 父类,可以直接 享受 父类中已经封装好的方法,不需要再次开发

? 子类 中应该根据 职责,封装 子类特有的 属性和方法

2.专业术语

? Dog 类是 Animal 类的子类,Animal 类是 Dog 类的父类,Dog 类从 Animal 类继承

? Dog 类是 Animal 类的派生类,Animal 类是 Dog 类的基类,Dog 类从 Animal 类派生

3.继承的传递性

? C 类从 B 类继承,B 类又从 A 类继承

? 那么 C 类就具有 B 类和 A 类的所有属性和方法

子类 拥有 父类 以及 父类的父类 中封装的所有 属性 和 方法

3.方法的重写

? 子类 拥有 父类 的所有 方法 和 属性

? 子类 继承自 父类,可以直接 享受 父类中已经封装好的方法,不需要再次开发

应用场景

? 当 父类 的方法实现不能满足子类需求时,可以对方法进行 重写(override)

重写 父类方法有两种情况:

1.覆盖 父类的方法

2.对父类方法进行 扩展

1.覆盖父类的方法

? 如果在开发中,父类的方法实现 和 子类的方法实现,完全不同

? 就可以使用 覆盖 的方式,在子类中 重新编写 父类的方法实现

具体的实现方式,就相当于在 子类中 定义了一个 和父类同名的方法并且实现

重写之后,在运行时,只会调用 子类中重写的方法,而不再会调用 父类封装的方法

2.对父类方法进行 扩展

? 如果在开发中,子类的方法实现中包含父类的方法实现

? 父类原本封装的方法实现 是 子类方法的一部分

? 就可以使用扩展的方式

1.在子类中 重写 父类的方法

2.在需要的位置使用 super().父类方法 来调用父类方法的执行

3.代码其他的位置针对子类的需求,编写 子类特有的代码实现

关于 super

? 在 Python 中 super 是一个 特殊的类

? super() 就是使用 super 类创建出来的对象

? 最常 使用的场景就是在 重写父类方法时,调用 在父类中封装的方法实现

调用父类方法的另外一种方式(知道)

在 Python 2.x 时,如果需要调用父类的方法,还可以使用以下方式:

父类名.方法(self)

? 这种方式,目前在 Python 3.x 还支持这种方式

? 这种方法 不推荐使用,因为一旦 父类发生变化,方法调用位置的 类名 同样需要修改

提示

? 在开发时,父类名 和 super() 两种方式不要混用

? 如果使用 当前子类名 调用方法,会形成递归调用,出现死循环

父类的 私有属性 和 私有方法

子类对象 不能 在自己的方法内部,直接 访问 父类的 私有属性 或 私有方法

子类对象 可以通过 父类 的 公有方法 间接 访问到 私有属性 或 私有方法

? 私有属性、方法 是对象的隐私,不对外公开,外界 以及 子类都不能直接访问

? 私有属性、方法 通常用于做一些内部的事情

案例示例

class?A: ????def?__init__(self): ????????num1?=?1 ????????__num2?=?2 ????def?__test(self): ????????pass def?test(self): ????????print(self.__num2) ????????print(self.__test()) ????????pass??? class?B(A): ????def?demo(self): ????????pass

? B 的对象不能直接访问 __num2 属性

? B 的对象不能在 demo 方法内访问 __num2 属性

? B 的对象可以在 demo 方法内,调用父类的 test 方法

父类的 test 方法内部,能够访问 __num2 属性和 __test 方法

2.3.2 继承(多继承)

1.概念

? 子类 可以拥有 多个父类,并且具有 所有父类 的 属性 和 方法

例如:孩子 会继承自己 父亲 和 母亲 的 特性

2.语法

class?子类名(父类名1,?父类名2...) ????pass

3.注意事项

问题的提出

? 如果 不同的父类 中存在 同名的方法,子类对象 在调用方法时,会调用 哪一个父类中的方法呢?

提示:开发时,应该尽量避免这种容易产生混淆的情况! —— 如果 父类之间 存在 同名的属性或者方法,应该 尽量避免 使用多继承

4.Python 中的 MRO —— 方法搜索顺序(知道)

Python 中针对 类 提供了一个 内置属性 mro 可以查看 方法 搜索顺序

MRO 是 method resolution order,主要用于 在多继承时判断 方法、属性 的调用 路径

print(C.mro)

输出如下结果:

(<class ‘main.C’>, <class ‘main.A’>, <class ‘main.B’>, <class ‘object’>)

在搜索方法时,是按照 mro 的输出结果 从左至右 的顺序查找的

如果在当前类中 找到方法,就直接执行,不再搜索

如果 没有找到,就查找下一个类 中是否有对应的方法,如果找到,就直接执行,不再搜索

如果找到最后一个类,还没有找到方法,程序报错

5.新式类与旧式(经典)类

object 是 Python 为所有对象提供的 基类,提供有一些内置的属性和方法,可以使用 dir 函数查看

? 新式类:以 object 为基类的类,推荐使用

? 经典类:不以 object 为基类的类,不推荐使用

? 在 Python 3.x 中定义类时,如果没有指定父类,会 默认使用 object 作为该类的 基类 —— Python 3.x 中定义的类都是 新式类

? 在 Python 2.x 中定义类时,如果没有指定父类,则不会以 object 作为 基类

新式类 和 经典类 在多继承时 —— 会影响到方法的搜索顺序

为了保证编写的代码能够同时在 Python 2.x 和 Python 3.x 运行

今后在定义类时,如果没有父类,建议统一继承自 object

class?类名(object): ????pass

2.4.1 多态

面向对象三大特性

封装根据职责将属性和方法封装到一个抽象的类中

1.定义类的准则

继承实现代码的重用,相同的代码不需要重复的编写

2.设计类的技巧

子类针对自己特有的需求,编写特定的代码

? 多态 不同的 子类对象 调用相同的 父类方法,产生不同的执行结果

? 多态 可以 增加代码的灵活度

? 以 继承 和 重写父类方法 为前提

? 是调用方法的技巧,不会影响到类的内部设计

示意图

2.案例演练

class?Dog(object):

def?__init__(self,?name): ????????self.name?=?name

def?game(self): ????????print("%s?蹦蹦跳跳的玩耍..."?%?self.name)

class?XiaoTianDog(Dog):

def?game(self): ????????print("%s?飞到天上去玩耍..."?%?self.name)

class?Person(object):

def?__init__(self,?name): ????????self.name?=?name

def?game_with_dog(self,?dog):

print("%s?和?%s?快乐的玩耍..."?%?(self.name,?dog.name))

#?让狗玩耍 ????????dog.game()

#?1.?创建一个狗对象 #?wangcai?=?Dog("旺财") wangcai?=?XiaoTianDog("飞天旺财")

#?2.?创建一个小明对象 xiaoming?=?Person("小明")

#?3.?让小明调用和狗玩的方法 xiaoming.game_with_dog(wangcai)

案例小结

? Person类中只需要让狗对象调用game方法,而不关心具体是什么狗

? game 方法是在 Dog 父类中定义的

? 在程序执行时,传入不同的 狗对象 实参,就会产生不同的执行效果

多态 更容易编写出出通用的代码,做出通用的编程,以适应需求的不断变化!

2.5 类属性和类方法

回顾之前的实例化

使用面相对象开发,第 1 步 是设计 类

使用 类名() 创建对象,创建对象的动作有两步:

1.在内存中为对象 分配空间

2.调用初始化方法 init 为 对象初始化

对象创建后,内存 中就有了一个对象的 实实在在 的存在 —— 实例

因此,通常也会把:

? 创建出来的 对象 叫做 类 的 实例

? 创建对象的 动作 叫做 实例化

? 对象的属性 叫做 实例属性

? 对象调用的方法 叫做 实例方法

在程序执行时:

1.对象各自拥有自己的实例属性

2.调用对象方法,可以通过self.

? 访问自己的属性

? 调用自己的方法

结论

? 每一个对象 都有自己 独立的内存空间,保存各自不同的属性

? 多个对象的方法,在内存中只有一份,在调用方法时,需要把对象的引用 传递到方法内部

2.类是一个特殊的对象

Python 中 一切皆对象:

class AAA: 定义的类属于 类对象

obj1 = AAA() 属于 实例对象

在程序运行时,类 同样 会被加载到内存

在 Python 中,类 是一个特殊的对象 —— 类对象

在程序运行时,类对象 在内存中 只有一份,使用 一个类 可以创建出 很多个对象实例

除了封装 实例 的 属性 和 方法外,类对象 还可以拥有自己的 属性 和 方法

? 类属性

? 类方法

通过 类名. 的方式可以 访问类的属性 或者 调用类的方法

3.类属性和实例属性

概念和使用

? 类属性 就是给 类对象 中定义的 属性

? 通常用来记录 与这个类相关 的特征

? 类属性 不会用于记录 具体对象的特征

示例需求

定义一个 工具类

每件工具都有自己的 name

需求 —— 知道使用这个类,创建了多少个工具对象?

class Tool(object):

#?使用赋值语句,定义类属性,记录创建工具对象的总数 ??count?=?0

def?__init__(self,?name): ??????self.name?=?name

#?针对类属性做一个计数+1 ??????Tool.count?+=?1

创建工具对象

tool1 = Tool(“斧头”)

tool2 = Tool(“榔头”)

tool3 = Tool(“铁锹”)

知道使用 Tool 类到底创建了多少个对象?

print(“现在创建了 %d 个工具” % Tool.count)

4.属性的获取机制(科普)

? 在 Python 中 属性的获取 存在一个 向上查找机制 ==> 作用域

1.首先在对象内部 查找对象属性,

2.没有找到就会 向上寻找类属性

访问类属性有两种方式:

1.类名.类属性

2.对象.类属性 (不推荐)

注意

? 如果使用 对象.类属性 = 值 赋值语句,只会 给对象添加一个属性,而不会影响到 类属性的值

2.6 类方法和静态方法

? 类方法

类属性 就是针对 类对象 定义的属性

使用 赋值语句 在 class 关键字下方可以定义 类属性

类属性 用于记录 与这个类相关 的特征

类方法 就是针对 类对象 定义的方法

在 类方法 内部可以直接访问 类属性 或者调用其他的 类方法

2.类方法语法

@classmethod def?类方法名(cls): ????pass

? 类方法需要用 修饰器 @classmethod 来标识,告诉解释器这是一个类方法

? 类方法的 第一个参数 应该是 cls

? 由 哪一个类 调用的方法,方法内的 cls 就是 哪一个类的引用

? 这个参数和 实例方法 的第一个参数是 self 类似

? 提示 使用其他名称也可以,不过习惯使用 cls

? 通过 类名. 调用 类方法,调用方法时,不需要传递 cls 参数

? 在方法内部

? 可以通过 cls. 访问类的属性

? 也可以通过 cls. 调用其他的类方法

3.静态方法

在开发时,如果需要在 类 中封装一个方法,这个方法:

?既 不需要 访问 实例属性 或者调用 实例方法

?也 不需要 访问 类属性 或者调用 类方法

语法

@staticmethod

def 静态方法名():

pass

静态方法 需要用 修饰器 @staticmethod 来标识,告诉解释器这是一个静态方法

通过 类名. 调用 静态方法

class Dog(object):

#?狗对象计数 ??dog_count?=?0 ?? ??@staticmethod ??def?run(): ?????? ??????#?不需要访问实例属性也不需要访问类属性的方法 ??????print("狗在跑...")

def?__init__(self,?name): ??????self.name?=?name

案例小结

1.实例方法 —— 方法内部需要访问实例属性

? 实例方法 内部可以使用 类名. 访问类属性

3.静态方法 —— 方法内部,不需要访问 实例属性 和 类属性

提问

如果方法内部 即需要访问 实例属性,又需要访问 类属性,应该定义成什么方法?

答案

应该定义 实例方法

因为,类只有一个,在 实例方法 内部可以使用 类名. 访问类属性

class Game(object):

#?游戏最高分,类属性 ??top_score?=?0

@staticmethod ??def?show_help(): ??????print("帮助信息:让僵尸走进房间") ?????? ??@classmethod ??def?show_top_score(cls): ??????print("游戏最高分是?%d"?%?cls.top_score)

def?__init__(self,?player_name): ??????self.player_name?=?player_name

def?start_game(self): ??????print("[%s]?开始游戏..."?%?self.player_name) ?????? ??????#?使用类名.修改历史最高分 ??????Game.top_score?=?999

1. 查看游戏帮助

Game.show_help()

2. 查看游戏最高分

Game.show_top_score()

3. 创建游戏对象,开始游戏

game = Game(“小明”)

game.start_game()

4. 游戏结束,查看游戏最高分

Game.show_top_score()

Bybit是一家全球性数字货币衍生品交易平台,总部位于新加坡,创始团队由顶级区块链投资人与金融领域高管组成。

通过该链接https://partner.bybit.com/b/quantfounder

注册Bybit可享受优惠手续费。maker:-0.025%;taker:0.075%。

—-

编译者/作者:盘古私募量化孵化

玩币族申明:玩币族作为开放的资讯翻译/分享平台,所提供的所有资讯仅代表作者个人观点,与玩币族平台立场无关,且不构成任何投资理财建议。文章版权归原作者所有。

LOADING...
LOADING...