我的python学习之路-oop面向对象
本节内容:
一、类的基础
二、封装
三、继承
四、多态
五、魔术方法
5.9 __add__ 魔术方法 (与之相关的 __radd__ 反向加法)
六、魔术属性
一、类的基础
1、类的定义
# 推荐使用 class MyCar(): pass class MyCar: pass class MyCar(object): pass
2、类的实例化
class MyCar(): pass # 类的实例化 / 实例化对象 obj = MyCar() print(obj)
3、类的基本结构
- 成员属性
- 成员方法
class MyCar(): # 成员属性 color = "粉色系" # 成员方法 def didi(): print("会滴滴的叫")
4、类的命名
类的命名 => 推荐使用大驼峰命名法;
mycar => MyCar
mycat => MyCat
chengfabiao => ChengFaBiao
二、封装
封装等级:
- 公有:在类的内部和外部都可以访问到
- 私有: 在类的内部可以使用,再类外无法调用
成员:
- 成员属性
- 成员方法
调用:
- 对象.成员属性
- 对象.成员方法
绑定方法:
- 绑定到对象:对象.类中方法()时,系统会自动把该对象当成参数传递到方法中;
- 绑定到类 :对象.类中方法()或者类.方法()时,系统会自动把该类当成参数传递到方法中
1.封装-对象的相关操作
定义一个类
class Car(): # 公有成员属性 color = "黄色" # 私有成员属性 __price = "200多万" # 公有方法 def run(self): # 类内调用公有成员 self <=> obj print(self.color,"内部") # 类内调用私有成员 print(self.__price) print("小车每秒140米的速度前进") # 私有方法 def __drive(): print("小车可以无人驾驶")
(1)实例化的对象访问公有成员属性和方法
# 实例化对象
obj = Car()
# 访问属性 print(obj.color,"<外部>") # print(obj.__price) #error # 访问方法 obj.run() # obj.__drive() #error
(2)实例化的对象动态添加公有成员属性和方法
obj优先调用自己的,在调用类的,都没有报错
1) 、 添加成员属性
obj.engine = "16缸发动机" obj.color = "绿色" # 优先调用对象自己的颜色 print(obj.engine) print(obj.color) obj.run() # __dict__ 查看对象或者类中的内部成员,返回字典 print(obj.__dict__) print(Car.__dict__)
2)、添加成员方法
注意点: 对象.类外方法()时,系统不会自动把该对象当成参数传递到该方法中
(1)、添加无参方法
def dahuangfeng(): print("变形~ 我叫大黄蜂") obj.dahuangfeng = dahuangfeng obj.dahuangfeng() print(obj.__dict__)
(2)、添加有参方法
基本版:
def qingtianzhu(name): print("变形~ 我叫{}".format(name)) obj.qingtianzhu = qingtianzhu obj.qingtianzhu("一柱擎天")
升级版 (手动传递obj),由于要用对象中的其他的属性,所以要传递obj
def qingtianzhu(obj,name): print( "变形~ 我叫{}".format(name) , "颜色为{}".format(obj.color) ) obj.qingtianzhu = qingtianzhu obj.qingtianzhu(obj,"擎天柱")
究极版 (自动传递obj)
MethodType => 创建绑定方法(绑定到对象) 让系统自动帮助我们传递obj对象
import types """types.MethodType(函数,对象)""" func = types.MethodType(qingtianzhu,obj) print(func) obj.qingtianzhu = func obj.qingtianzhu("擎天柱")
(3) 添加lambda 表达式
obj.hongzhizhu = lambda : print("变形~ 我是反派角色红蜘蛛") obj.hongzhizhu()
2、封装 - 类相关操作
定义一个类
class Taxi(): # 公有成员属性 platenum = "粤B 666888" # 私有成员属性 __earn = "12000" # 公有方法 def lake(): print("出租车经常拉客人~") # 私有方法 def __ranquan(): print("部分司机绕圈圈~")
(1)定义的类访问公有成员属性和方法
obj = Taxi() """类中的无参方法只能类来调用;""" # obj.lake() # 成员属性 print(Taxi.platenum) # Taxi.__earn error # 成员方法 Taxi.lake()
(2)定义的类动态添加公有成员属性和方法
(1)、动态添加成员属性
Taxi.luntai = "米其林" print(Taxi.luntai) print(obj.luntai) #米其林 对用可以调用 print(Taxi.__dict__) print(obj.__dict__) #{} 看看出对象和类是两个内存空间
(2)、动态添加成员方法
(1) 无参方法
def fangxiangpan(): print("我是制造方向盘的方法") Taxi.fangxiangpan = fangxiangpan Taxi.fangxiangpan()
(2) 有参方法
def engin(name): print("我是制造{}的方法".format(name)) Taxi.engin = engin Taxi.engin("EA888")
(3) lambda表达式
Taxi.zuoyi = lambda : print("我是制造加热座椅的方法") Taxi.zuoyi()
3、注意点: 对象和类之间的不同
(1)对象去调用类中方法时,系统都会默认传递该对象参数;
(2)对象可以默认调用类中的公有成员,反过来,类不能调用对象中的相关成员.
(3)一个类可以创建多个对象,而对象和对象之间是彼此独立的;
4、访问类中私有成员
定义一个类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Plane(): 2 3 # 公有成员属性 4 captain = "李雅琪" 5 6 # 私有成员属性 7 __airsister = "10个空姐" 8 9 # 公有成员方法 10 def fly(self): 11 print("飞机飞到平流层,可以飞机的机身的抖动") 12 13 # 私有成员方法 14 def __price(self): 15 print("飞机的价格保密") 16 17 # 公有无参成员方法 18 def fly2(): 19 print("飞机在降落时,落地的一瞬间会向上弹起,请记好安全带") 20 21 # 私有无参成员方法 22 def __info(): 23 print("关于飞机中的机长和空姐的信息保密") 24 25 # 利用公有方法调取私有成员[对象操作] 26 def pub_info1(self): 27 print(self.__airsister) 28 self.__price() 29 30 # 利用公有方法调取私有成员[类操作] 31 def pub_info2(): 32 print(Plane.__airsister) 33 Plane.__info()
(1 ).方法一 私有化的实现方式:改名策略 (不推荐,破坏了封装性)
# 实例化对象 obj = Plane() print(Plane.__dict__) # 类去访问私有成员属性 print(Plane._Plane__airsister) # 类去访问私有成员方法 Plane._Plane__info() # 对象去访问私有成员属性 obj._Plane__airsister # 对象去访问私有成员方法 obj._Plane__price()
2.方法二 利用一个公有方法,间接调用私有成员 (推荐)
obj.pub_info1()
Plane.pub_info2()
注意点:如果无参只能类来调取,如果有参,对象和类都能调取
# obj.pub_info2() #error Plane.pub_info1(obj)
5、删除类对象中公有成员属性方法
1.删除成员时,一定要注意,该成员归属于谁,如果对象中没有该成员,只有使用的权利,没有删除和修改的权利
2.对象获取成员时,先看自己空间有没有,如果有就调取,否则上类中成员寻找,如果类中也没有,直接报错
定义一个类:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Plane(): 2 3 # 公有成员属性 4 captain = "李雅琪" 5 6 # 私有成员属性 7 __airsister = "10个空姐" 8 9 # 公有成员方法 10 def fly(self): 11 print("飞机飞到平流层,可以飞机的机身的抖动") 12 13 # 私有成员方法 14 def __price(self): 15 print("飞机的价格保密") 16 17 # 公有无参成员方法 18 def fly2(): 19 print("飞机在降落时,落地的一瞬间会向上弹起,请记好安全带") 20 21 # 私有无参成员方法 22 def __info(): 23 print("关于飞机中的机长和空姐的信息保密") 24 25 # 利用公有方法调取私有成员[对象操作] 26 def pub_info1(self): 27 print(self.__airsister) 28 self.__price() 29 30 # 利用公有方法调取私有成员[类操作] 31 def pub_info2(): 32 print(Plane.__airsister) 33 Plane.__info()
1、删除对象中的属性
obj.captain = "家营和" # 不能删除类中的,只能自己添加 print(obj.__dict__) del obj.captain print(obj.captain,"<111>")
2、删除对象中的方法
obj.pub_info1 = lambda : print("我是pub_info方法") del obj.pub_info1
3、 删除类中的属性
del Plane.captain #print(Plane.captain) error # print(obj.captain,"<2222>") error
4、删除类中的方法
del Plane.pub_info1 # Plane.pub_info1(obj) error # obj.pub_info1() error
三 、继承
继承:一个类除了自身所拥有的属性方法之外,还获取了另外一个类的成员属性和方法
被继承的就是父类(基类,超类)
继承的就是子类(衍生类)
python中所有类的父类是object
1、单继承
class Human(): property1 = "远古人类不穿衣服" def fire(self): print("远古人类钻木去火") def drinkblood(self): print("远古人类茹毛饮血") def __mao(self): print("远古人类一身毛,不能碰") class Man(Human): pass
1、子类继承了父类之后,子类可以使用父类的公有成员
obj = Man() print(obj.property1)
2、子类继承了父类之后,子类不能使用父类的私有成员
class Woman(Human): def pub_func(self): self.__mao() obj = Woman() # obj.pub_func() error
3、 子类继承了父类之后,子类可以重写父类的公有成员
class Children(Human): def drinkblood(self): print("刚出生的小孩只能喝奶奶") obj = Children() obj.drinkblood()
4、总结
在继承的环境当中,对象的调取顺序:
先查看自己对象中是否含有该成员 => 自己的类是否含有 => 该类的父类是否含有 => 报错
2、多继承
1.基本用法
class Father(): f_pty = "风流倜傥,玉树临风,一枝梨花压海棠" def f_hobby(self): print("打麻将,吃喝嫖赌,开跑车约妹子") class Mother(): m_pty = "倾国倾城,貌美如花,一直红杏出墙来" def m_hobby(self): print("打麻将,蹦野迪,勾引小鲜肉") class Daughter(Father,Mother): pass obj = Daughter() print(obj.f_pty) obj.m_hobby()
2.深度使用
(1)super本身是一个类 super()是一个对象 用于调用父类的绑定方法
(2)super() 只应用在绑定方法中,默认自动传递self对象 (前提:super所在作用域存在self)
(3)super用途: 解决复杂的多继承调用顺序
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Father(): 2 pty = "风流倜傥,玉树临风,一枝梨花压海棠" 3 def hobby(self): 4 print(self) 5 print("打麻将,吃喝嫖赌,开跑车约妹子") 6 7 class Mother(): 8 pty = "倾国倾城,貌美如花,一直红杏出墙来" 9 def hobby(self): 10 print("打麻将,蹦野迪,勾引小鲜肉") 11 12 class Son(Father,Mother): 13 pty = "可爱,有趣,爱学习,爱劳动,三道杠" 14 15 def hobby(self): 16 print("喜欢打游戏,lol,wow.dnf.ddo,cs,cf") 17 18 # 1.使用类调用类中成员 19 def skill1(self): 20 # 调用mother中的成员 21 print(Mother.pty) 22 Mother.hobby(self) 23 24 # 调用father中的成员 25 print(Father.pty) 26 # Father.hobby() 27 28 # 2.使用对象调用类中成员 29 """obj调用成员时,会按照 obj成员 -> 子类成员 -> 父类成员""" 30 def skill2(self): 31 print(self.pty) 32 # obj.hobby() error 33 self.hobby() 34 35 # 3.使用super调用类中成员 36 """1.super只调用父类的绑定方法 2.会自动把该对象当成参数进行传递""" 37 def skill3(self): 38 print(super) 39 print(super()) 40 print(super().pty) 41 super().hobby() 42 43 obj = Son() 44 print("<=======1========>") 45 obj.skill1() 46 print("<=======2========>") 47 obj.skill2() 48 print("<=======3========>") 49 obj.skill3()
3、菱形继承
class Human(): pty = 4 def feelT(self): print("天热了,脱毛1") print(self.pty) print("天冷了,穿貂2") class Man(Human): pty = 3 def feelT(self): print("天热了,光膀子3") super().feelT() print("天冷了,穿貂4") class Woman(Human): pty = 2 def feelT(self): print("天热了,脱衣服5") super().feelT() print("天冷了,多喝热水6") class Children(Man,Woman): pty = 1 def feelT(self): print("天热了,光屁股7") super().feelT() print("天冷了,喝奶8") obj = Children() obj.feelT() # 7 3 5 1 2 6 4 8 print(obj.pty)#1
mro列表:方法解析顺序列表
类.mro() => 方法解析顺序列表
super调用的顺序要依赖mro列表所呈现的顺序,依次调用;
作用: super用途: 解决复杂的多继承调用顺序(菱形继承)
super要点:
1.super只调用父类成员
2.super调用父类成员采用广度优先原则(依照类.mro列表顺序调用)
3.super调用父类方法时,会自动传递该对象参数
4、相关函数
(1)、.issubclass 判断子类与父类 (类与类之间的关系)
issubclass在判断子父关系时候,只要在一条继承链上,有继承关系即可
1).issubclass(子类,父类)
2).issubclass(子类,(父类1,父类2,父类3 ... ))
(2)、isinstance 判断对象的类型 (对象与类之间关系)
1).isinstance(对象,类)
2)isinstance(对象,(类1,类2,类3)
四 、多态
1、基本概念及使用例子
多态 : 不同的子类对象,调用相同的父类方法,产生不同的执行结果
特征 : 继承 重写 针对于对象
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Soldier(): 2 # 攻击方法 3 def attack(self): 4 pass 5 6 # 撤退方法 7 def back(self): 8 pass 9 10 11 class Army(Soldier): 12 def attack(self): 13 print("手撕鬼子,包子手雷") 14 15 def back(self): 16 print("飞檐走壁,日行八百,夜行一千") 17 18 class Navy(Soldier): 19 def attack(self): 20 print("扔鱼叉,勤撒网,往回拉鬼子") 21 22 def back(self): 23 print("潜水,划水,水遁,下水憋气30个小时") 24 25 class AirForce(Soldier): 26 def attack(self): 27 print("射导弹,扔手雷") 28 29 def back(self): 30 print("契机跳伞,落地成盒") 31 32 # 创建陆军士兵 33 objArmy = Army() 34 # 创建海军士兵 35 objNavy = Navy() 36 # 创建空军士兵 37 objAirForce = AirForce() 38 39 # 各就位准备 40 lst = [objArmy,objNavy,objAirForce] 41 42 strvar = """ 43 各就位准备,将军请下令: 44 1.全体出击 45 2.全体撤退 46 3.陆军上,其他兵种撤退 47 """ 48 49 num = input(strvar) 50 for i in lst: 51 # print(i) 52 if num == "1": 53 i.attack() 54 elif num == "2": 55 i.back() 56 elif num == "3": 57 # 判断对象类型是陆军 58 if isinstance(i,Army): 59 i.attack() 60 else: 61 i.back() 62 else: 63 print("风大太,我听不见~") 64 break 65
五、魔术方法
定义:系统自动调用的方法,按照触发机制调用
1、 __init__构造方法
触发时机:实例化对象,初始化的时候触发
功能:为对象添加成员
参数:参数不固定,至少一个self参数
返回值:无
(1) 基本使用-无参数的
class MyClass(): def __init__(self): self.name = "~李琦~" print("构造方法被触发了... ") # 实例化对象 obj = MyClass() print(obj.name)
(2)带有参数的构造方法
class MyClass(): def __init__(self,name): self.name = name # 在实例化对象时,给与构造方法实参 obj1 = MyClass("朱培峰") obj2 = MyClass("黄常见") print(obj1.name) print(obj2.name)
(3)类可以是一个,对象可以是多个,不同的对象之间数据彼此隔离
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Children(): 2 3 # 构造方法 4 def __init__(self,name,skin): 5 # 为对象添加成员 6 self.name = name 7 self.skin = skin 8 # 公有成员方法(绑定到对象) 9 def cry(self): 10 print("小孩一生产出来,就会哇哇哇的哭") 11 12 # 公有成员方法(绑定到对象) 13 def eat(self): 14 print("小孩一生产出来,就会吃奶奶") 15 16 # 私有成员方法(绑定到对象) 17 def __laugh(self): 18 print("小孩一生产出来,就仰天长笑,老子终于出来了.") 19 20 # 面向对象的写法(让对象操作一切) 推荐 21 def info1(self): 22 print("小孩的姓名是{},小孩的肤色是{}".format(self.name , self.skin) ) 23 24 # 面向过程写法(普通的函数传参) 25 def info2(self,name,skin): 26 print("小孩的姓名是{},小孩的肤色是{}".format(name ,skin) ) 27 28 29 wanggangdan = Children("王刚单","综色") 30 wanggangdan.info1() 31 wanggangdan.info2("王钢单","白色") 32 wanggangdan.cry() 33 34 wangtiechui = Children("王铁锤","黑色") 35 wangtiechui.info1() 36 wangtiechui.eat() 37 38 wangbaoqiang = Children("王宝强","绿色") 39 wangbaoqiang.info1() 40 # wangbaoqiang.__laugh() error
2、__new__ 魔术方法
触发时机:实例化类生成对象的时候触发(触发时机在__init__之前)
功能:控制对象的创建过程
参数:至少一个cls接受当前的类,其他根据情况决定
返回值:通常返回对象或None
1.基本使用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class OtherClass(): 2 pty = 200 3 obj2 = OtherClass() 4 5 class MyClass(): 6 pty = 1 7 def __new__(cls): 8 print("__new__方法被触发 ... ") 9 print(cls) 10 print("<===========>") 11 12 # 返回本类对象 (借父生子) 13 # 类.方法(cls) 14 # return object.__new__(cls) 15 # 不返回对象 16 # return None 17 # 返回其他类对象 18 return obj2 19 20 obj = MyClass() 21 print(obj) 22 print(obj.pty)
2.__new__ 和 __init__ 的触发时机
__new__ 是在造对象时触发
__init__ 有对象之后,初始化对象的时候自动触发
先有对象,在初始化;
3.__new__ 和 __init__ 参数需要一一对应
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class MyClass(): 2 3 def __new__(cls,name): 4 print(333) 5 return object.__new__(cls) 6 def __init__(self,name): 7 print(444) 8 self.name = name 9 10 obj = MyClass("李琦") 11 print(obj.name) 12 13 # 在__new__中加上收集参数,以不变应万变 14 class MyClass(): 15 16 def __new__(cls,*args,**kwargs): 17 print(333) 18 return object.__new__(cls) 19 def __init__(self,name,sex,age): 20 print(444) 21 self.name = name 22 self.sex = sex 23 self.age = age 24 obj = MyClass("朱培峰","女性","100") 25 print(obj.name) 26 print(obj.sex) 27 print(obj.age)
4.注意点
如果没有创建出对象,不会触发构造方法 ...
如果返回的不是本类对象,不会触发构造方法 ...
3、单态(例)模式
同一个类,无论实例化多少次,都有且只有一个对象
作用: 可以减少内存空间的浪费,提升代码执行效率
场景: 如果不需要在创建对象时,在类外额外为当前对象添加成员,就可以使用单态模式;
(1) 基本使用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class SingleTon(): 2 # 类中私有成员属性 3 __obj = None 4 5 def __new__(cls): 6 print(cls) # <class '__main__.SingleTon'> 7 # 类.私有成员属性 8 if cls.__obj is None: 9 # 存储创建的对象在私有成员__obj当中 10 # 类.私有成员属性 = 值(对象) 11 cls.__obj = object.__new__(cls) 12 # 返回该对象 13 return cls.__obj 14 15 obj1 = SingleTon() 16 obj2 = SingleTon() 17 obj3 = SingleTon() 18 print(obj1) 19 print(obj2) 20 print(obj3)
代码解析:
obj1 = SingleTon() 触发__new__魔术方法 if cls.__obj is None: 条件满足,创建对象赋值给私有成员__obj return 当前创建的对象
obj2 = SingleTon() 触发__new__魔术方法 return cls.__obj
obj3 = SingleTon() 触发__new__魔术方法 return cls.__obj
(2) 注意点
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class SingleTon(): 2 __obj = None 3 def __new__(cls,*args,**kwargs): 4 if cls.__obj is None: 5 cls.__obj = object.__new__(cls) 6 return cls.__obj 7 8 def __init__(self,name): 9 self.name = name 10 11 obj1 = SingleTon("王永娟") 12 obj2 = SingleTon("荷叶") 13 print(obj1.name) 14 print(obj2.name) 15 16 print(obj1,obj2) 17 print(obj1 is obj2) ##相等 同一地址
4、__del__ 魔术方法(析构方法)
触发时机:当对象被内存回收的时候自动触发[1.页面执行完毕回收所有变量 2.所有对象被del的时候]
功能:对象使用完毕后资源回收
参数:一个self接受对象
返回值:无
1.基本使用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 # 1.基本使用 2 class LangDog(): 3 # 构造方法 4 def __init__(self,name): 5 self.name = name 6 7 # 析构方法 8 def __del__(self): 9 print("析构方法被触发 ... ") 10 11 # 1.页面执行完毕回收所有变量,自动触发 12 obj1 = LangDog("小白土狗") 13 print(obj1.name) 14 # 2.所有对象被del的时候,自动触发 15 # print("<==========start==========>") 16 # del obj1 17 # print("<==========end==========>") 18 # 3.注意点 19 """当一个数据没有任何变量引用的时候,才会真正的被内存释放掉;""" 20 obj2 = obj1 21 obj3 = obj1 22 print(obj2 is obj3) 23 print(obj1,obj2,obj3) 24 print("<==========start==========>") 25 del obj1 26 del obj2 27 del obj3 28 print("<==========end==========>")
2.模拟文件操作
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import os 2 class ReadFile(): 3 4 def __new__(cls,filename): 5 # 判断文件是否存在,在创建对象 6 if os.path.exists(filename): 7 return object.__new__(cls) 8 else: 9 print("抱歉,该文件不存在") 10 11 def __init__(self,filename): 12 # 打开文件 13 self.fp = open(filename,mode="r",encoding="utf-8") 14 15 def readfile(self): 16 # 读取文件 17 data = self.fp.read() 18 return data 19 20 def __del__(self): 21 # 关闭文件 22 self.fp.close() 23 24 obj = ReadFile("ceshi1.txt") 25 # obj = ReadFile("ceshi1.txt234242234423") 文件不存在,不会创建对象 26 res = obj.readfile() 27 print(res)
5、__call__ 魔术方法
触发时机:把对象当作函数调用的时候自动触发
功能: 模拟函数化操作
参数: 参数不固定,至少一个self参数
返回值: 看需求
(1) 基本用法
class MyClass(): def __call__(self): print("__call__ 方法被触发 ... ") obj = MyClass() obj()
(2) 模拟洗衣服的过程
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Wash(): 2 def __call__(self,something): 3 print("正在{}".format(something)) 4 self.step1() 5 self.step2() 6 self.step3() 7 return "洗完了" 8 9 def step1(self): 10 print("脱衣服,把衣服扔进洗衣机") 11 12 def step2(self): 13 print("扔点蓝月亮,洗衣粉,洗衣皂,金纺... ") 14 15 def step3(self): 16 print("穿上去,等于晾干") 17 18 obj = Wash() 19 20 # 方法一 21 # obj.step1() 22 # obj.step2() 23 # obj.step3() 24 25 # 方法二 26 res = obj("洗衣服") 27 print(res)
(3) 模拟int操作
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 import math 2 class MyInt(): 3 def __call__(self,num): 4 5 # 判断是否是布尔类型,做转换 6 if isinstance(num,bool): 7 if num == True: 8 return 1 9 else: 10 return 0 11 12 # 判断是否是整型,做转换 13 elif isinstance(num,int): 14 return num 15 16 # 判断是否是浮点型,做转换 17 elif isinstance(num,float): 18 # 方法一 19 """ 20 a,b = str(num).split(".") 21 return eval(a) 22 """ 23 24 # 方法二 25 """ceil floor""" 26 """ 27 if num >= 0: 28 return math.floor(num) 29 else: 30 return math.ceil(num) 31 """ 32 33 # 简写 34 return math.floor(num) if num >= 0 else math.ceil(num) 35 36 # 判断是否是字符串 37 elif isinstance(num,str): 38 # 获取第一为是+或者-,后面全是纯数字,可以转换 39 if (num[0] == "+" or num[0] == "-") and num[1:].isdecimal(): 40 # 判定符号 41 if num[0] == "+": 42 sign = 1 43 else: 44 sign = -1 45 # 计算数据 46 return self.calc(num[1:],sign) 47 48 elif num.isdecimal(): 49 return self.calc(num) 50 51 else: 52 return "抱歉,这个算不了" 53 54 def calc(self,num,sign=1): 55 # print("<========================>") 56 res = num.lstrip("0") 57 if res == "": 58 return 0 59 return eval(res) * sign 60 61 62 # int 整型 浮点型 布尔型 纯数字字符串 63 myint = MyInt() 64 # 布尔型 65 res = myint(False) 66 print(res) 67 # 整型 68 res = myint(199) 69 print(res) 70 # 浮点型 71 res = myint(5.77) 72 res = myint(-5.77) 73 print(res , type(res)) 74 75 # 字符串 76 # res = myint("-00001111") 77 78 res = myint("asdfasdf") # -1111 ("-000000000000000000000000") 79 print("<============start============>") 80 print(res) 81 print("<============end============>") 82 83 """ 84 print(math.floor(3.15)) 85 print(int(3.15)) 86 87 print(math.ceil(-3.15)) 88 print(int(-3.15)) 89 90 91 print(math.floor(0)) 92 # print(int(0.13)) 93 94 """ 95 96 print(int("0000000000000000000012121121")) 97 print(int("+0000000000000000000012121121")) 98 print(int("-0000000000000000000012121121"))
6、__str__ 魔术方法
触发时机: 使用print(对象)或者str(对象)的时候触发
功能: 查看对象
参数: 一个self接受当前对象
返回值: 必须返回字符串类型
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Cat(): 2 gift = "抓老鼠" 3 def __init__(self,name): 4 self.name = name 5 6 def cat_info(self): 7 return "小猫名字叫{},天赋是{}".format(self.name,self.gift) 8 9 def __str__(self): 10 return self.cat_info() 11 12 # (了解) __repr__ = __str__ 13 14 tom = Cat("汤姆") 15 # 第一种触发方式 16 # print(tom) 17 # 第二种触发方法 18 res = str(tom) 19 print(res) 20 21 22 res = repr(tom) 23 print(res)
7、__repr__ 魔术方法
触发时机: 使用repr(对象)的时候触发
功能: 查看对象,与魔术方法__str__相似
参数: 一个self接受当前对象
返回值: 必须返回字符串类型
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Mouse(): 2 gift = "遛猫" 3 4 def __init__(self,name): 5 self.name = name 6 7 def mouse_info(self): 8 return "老鼠的名字{},天赋是{}".format(self.name,self.gift) 9 10 def __repr__(self): 11 return self.mouse_info() 12 13 14 jerry = Mouse("杰瑞") 15 res = repr(jerry) 16 print(res) 17 18 # 在打印或者str(对象) 仍然可以触发__repr__ 19 # 原因: 系统在底层加入了如下语句: __str__ = __repr__ 20 print(jerry) 21 res = str(jerry) 22 print(res)
8、__bool__ 魔术方法
触发时机:使用bool(对象)的时候自动触发
功能:强转对象
参数:一个self接受当前对象
返回值:必须是布尔类型
类似的还有如下等等(了解):
__complex__(self) 被complex强转对象时调用
__int__(self) 被int强转对象时调用
__float__(self) 被float强转对象时调用
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class MyClass(): 2 def __bool__(self): 3 return False 4 5 obj = MyClass() 6 # 强转对象时自动触发 7 print(bool(obj))
9、_add__ 魔术方法 (与之相关的 __radd__ 反向加法)
触发时机:使用对象进行运算相加的时候自动触发
功能:对象运算
参数:二个对象参数
返回值:运算后的值
类似的还有如下等等(了解):
__sub__(self, other) 定义减法的行为:-
__mul__(self, other) 定义乘法的行为:
__truediv__(self, other) 定义真除法的行为:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class MyClass(): 2 def __init__(self,num): 3 self.num = num 4 5 # 对象 在加号的左边,自动触发__add__魔术方法 6 def __add__(self,other): 7 print(self) # a 8 print(other)# 5 9 return self.num + other # 15 10 11 # 对象 在加号的右边,自动触发__radd__魔术方法 12 def __radd__(self,other): 13 print(self) # b 14 print(other)# 3 15 return self.num + 2 * other 16 17 # 写法一 18 a = MyClass(10) 19 res = a + 5 20 print(res) 21 22 # 写法二 23 b = MyClass(5) 24 res = 3 + b 25 print(res) 26 27 # 写法三 28 """ 29 先触发add方法:self => a , other => b return self.num + other => return 10 + b => res = 10 + b 30 再触发radd方法:self => b , other => 10 return 5 + 2 * 10 = 5 + 20 = 25 31 """ 32 res = a + b 33 print(res) 34 35 # 25 25 25
10、__len__ 魔术方法
触发时机:使用len(对象)的时候自动触发
功能:用于检测对象中或者类中某个内容的个数
参数:一个self接受当前对象
返回值:必须返回整型
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class MyClass(): 2 pty1 = 1 3 pty2 = 2 4 __pty3 = 3 5 __pty4 = 3 6 7 def func1(): 8 pass 9 def func2(): 10 pass 11 def __func3(): 12 pass 13 14 def __len__(self): 15 # 基本写法 16 """ 17 lst = [] 18 print(MyClass.__dict__) 19 dic = MyClass.__dict__ 20 for i in dic: 21 print(i,type(i)) 22 if not (i.startswith("__") and i.endswith("__")): 23 lst.append(i) 24 return len(lst) 25 """ 26 27 # 优化代码 28 return len([i for i in MyClass.__dict__ if not (i.startswith("__") and i.endswith("__"))]) 29 30 31 32 obj = MyClass() 33 res = len(obj) 34 print(res)
六、魔术属性
1、包含成员及例子
__dict__ 获取对象或类的内部成员结构
__doc__ 获取对象或类的内部文档
__name__ 获取类名函数名
__class__ 获取当前对象所属的类
__bases__ 获取一个类直接继承的所有父类,返回元组
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 class Yeye(): 2 pass 3 4 class Man(Yeye): 5 pass 6 7 class Woman(Yeye): 8 pass 9 10 class nalutao(Man,Woman): 11 """ 12 成员属性:hair , eye 13 成员方法:yingfenshen __yeyoushu 14 对类描述:描述漩涡鸣人这个人的相关信息 15 """ 16 17 hair = "金光色" 18 19 eye = "蓝色" 20 21 def yingfenshen(self): 22 print("使出影分身迷惑敌人") 23 24 def luo_xuan_wan(self,func): 25 print("使出螺旋丸法术 ... ") 26 res = func.__name__ 27 print(res , type(res)) 28 29 def __yeyoushu(self): 30 print("使出色诱术勾引敌人 ... ") 31 32 obj = nalutao() 33 # __dict__ 获取对象或类的内部成员结构 34 print(obj.__dict__) 35 print(nalutao.__dict__) 36 # __doc__ 获取对象或类的内部文档 37 print(obj.__doc__) 38 print(nalutao.__doc__ ) 39 40 # __name__ 获取类名函数名 41 def abcde(): 42 pass 43 44 obj.luo_xuan_wan(abcde) 45 46 # __class__ 获取当前对象所属的类 47 print(obj.__class__) 48 49 # __bases__ 获取一个类直接继承的所有父类,返回元组 50 tup = nalutao.__bases__ 51 print(tup)