我的python学习之路-oop面向对象

本节内容:

  一、类的基础

    1.1 类的定义

    1.2 .类的实例化

    1.3 类的结构

    1.4 类的命名

         二、封装

    2.1 封装-对象的操作

    2.2 封装-类的相关

    2.3  注意点-对象和类之间的不同

    2.4 访问类中的私有成员

    2.5 删除类对象中公有成员属性方法

  三、继承

    3.1 单继承

    3.2 多继承

  四、多态

    4.1基本概念及使用例子

   五、魔术方法

    5.1 __init__构造方法

    5.2 __new__ 魔术方法

    5.3 单态(例)模式

    5.4 __del__ 析构方法

    5.5__call__魔术方法

    5.6__str__魔术方法

    5.7__repr__魔术方法

    5.8__bool__ 魔术方法

    5.9 __add__ 魔术方法  (与之相关的 __radd__ 反向加法)

    5.10 __len__ 魔术方法

  六、魔术属性

    6.1包含成员及例子

 

一、类的基础

1、类的定义

# 推荐使用
class MyCar():
    pass
    
class MyCar:
    pass
    
class MyCar(object):
    pass

2、类的实例化

class MyCar():
    pass
# 类的实例化 / 实例化对象
obj = MyCar()
print(obj)

3、类的基本结构

  1. 成员属性
  2. 成员方法                
class MyCar():
    # 成员属性
    color = "粉色系"
    # 成员方法
    def didi():
        print("会滴滴的叫")

4、类的命名

类的命名 => 推荐使用大驼峰命名法;
mycar => MyCar
mycat => MyCat
chengfabiao => ChengFaBiao

二、封装

封装等级:

  1. 公有:在类的内部和外部都可以访问到
  2. 私有:  在类的内部可以使用,再类外无法调用

成员:

  1. 成员属性
  2. 成员方法

调用:

  1. 对象.成员属性
  2. 对象.成员方法

绑定方法:

  1. 绑定到对象:对象.类中方法()时,系统会自动把该对象当成参数传递到方法中;
  2. 绑定到类  :对象.类中方法()或者类.方法()时,系统会自动把该类当成参数传递到方法中

 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、访问类中私有成员

定义一个类

 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()
View Code

(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.对象获取成员时,先看自己空间有没有,如果有就调取,否则上类中成员寻找,如果类中也没有,直接报错

定义一个类:

 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()
View Code

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用途: 解决复杂的多继承调用顺序

 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()
View Code

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、基本概念及使用例子

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

特征 : 继承 重写 针对于对象

 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         
View Code

五、魔术方法

定义:系统自动调用的方法,按照触发机制调用

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)类可以是一个,对象可以是多个,不同的对象之间数据彼此隔离

 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
View Code

2、__new__ 魔术方法

触发时机:实例化类生成对象的时候触发(触发时机在__init__之前)
功能:控制对象的创建过程
参数:至少一个cls接受当前的类,其他根据情况决定
返回值:通常返回对象或None

 1.基本使用

 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)
View Code

2.__new__ 和 __init__ 的触发时机

__new__ 是在造对象时触发
__init__ 有对象之后,初始化对象的时候自动触发
先有对象,在初始化;

3.__new__ 和 __init__ 参数需要一一对应

 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)
View Code

4.注意点

如果没有创建出对象,不会触发构造方法 ...
如果返回的不是本类对象,不会触发构造方法 ...

3、单态(例)模式

同一个类,无论实例化多少次,都有且只有一个对象

作用: 可以减少内存空间的浪费,提升代码执行效率
场景: 如果不需要在创建对象时,在类外额外为当前对象添加成员,就可以使用单态模式;

(1) 基本使用

 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)
View Code

代码解析:
obj1 = SingleTon() 触发__new__魔术方法 if cls.__obj is None: 条件满足,创建对象赋值给私有成员__obj return 当前创建的对象
obj2 = SingleTon() 触发__new__魔术方法 return cls.__obj
obj3 = SingleTon() 触发__new__魔术方法 return cls.__obj

(2) 注意点

 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) ##相等 同一地址
View Code

4、__del__ 魔术方法(析构方法)

触发时机:当对象被内存回收的时候自动触发[1.页面执行完毕回收所有变量 2.所有对象被del的时候]
功能:对象使用完毕后资源回收
参数:一个self接受对象
返回值:无

1.基本使用

 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==========>")
View Code

2.模拟文件操作

 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)
View Code

5、__call__ 魔术方法

触发时机:把对象当作函数调用的时候自动触发

功能: 模拟函数化操作

参数: 参数不固定,至少一个self参数

返回值: 看需求

(1) 基本用法

class MyClass():
    def __call__(self):
        print("__call__ 方法被触发 ... ")
        
obj = MyClass()
obj()

(2) 模拟洗衣服的过程

 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)
View Code

(3) 模拟int操作

 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"))
View Code

6、__str__ 魔术方法

触发时机: 使用print(对象)或者str(对象)的时候触发

功能:     查看对象

参数:     一个self接受当前对象

返回值:   必须返回字符串类型

 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)
View Code

7、__repr__ 魔术方法

触发时机: 使用repr(对象)的时候触发

功能:     查看对象,与魔术方法__str__相似

参数:     一个self接受当前对象

返回值:   必须返回字符串类型

 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)
View Code

8、__bool__ 魔术方法

触发时机:使用bool(对象)的时候自动触发

功能:强转对象

参数:一个self接受当前对象

返回值:必须是布尔类型

类似的还有如下等等(了解):

__complex__(self)      被complex强转对象时调用

__int__(self)          被int强转对象时调用

__float__(self)        被float强转对象时调用

1 class MyClass():
2     def __bool__(self):
3         return False
4     
5 obj = MyClass()
6 # 强转对象时自动触发
7 print(bool(obj))
View Code

9、_add__ 魔术方法  (与之相关的 __radd__ 反向加法)

触发时机:使用对象进行运算相加的时候自动触发

功能:对象运算

参数:二个对象参数

返回值:运算后的值

类似的还有如下等等(了解):

__sub__(self, other)           定义减法的行为:-

__mul__(self, other)           定义乘法的行为:

__truediv__(self, other)       定义真除法的行为:

 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
View Code

10、__len__ 魔术方法

触发时机:使用len(对象)的时候自动触发 

功能:用于检测对象中或者类中某个内容的个数

参数:一个self接受当前对象

返回值:必须返回整型

 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)
View Code

 六、魔术属性

 1、包含成员及例子

 __dict__ 获取对象或类的内部成员结构
__doc__ 获取对象或类的内部文档
 __name__ 获取类名函数名
__class__ 获取当前对象所属的类
 __bases__ 获取一个类直接继承的所有父类,返回元组

 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)
View Code
原文地址:https://www.cnblogs.com/yj0405/p/14152491.html