目录

  • 面向对象编程

    • 1.什么是面向对象编程?

      • 面向过程编程思想
      • 面向对象编程思想
    • 2.什么是类?如何定义。
      • 类:
      • 对象
    • 3.如何产生对象?
      • 调用类时的事件:
    • 4.对象属性的查找顺序:
    • 5.类内部的函数:
    • 一切皆对象
    • 人狗大作战
    • 继承
      • 1.什么是继承?
      • 2.继承的好处?
      • 3.如何继承?
      • 4.继承背景下,对象.属性的查找顺序
      • 5.派生:
      • 6.重用父类的属性与方法,并派生出自己的属性与方法。
      • 7.新式类与经典类
      • 8.钻石继承(菱形继承)背景下,属性查找顺序
      • 9..mro: 类的内置方法
    • 1.组合
      • 是什么组合?
      • 组合的好处(作用)
      • 组合如何实现?
    • 2.封装:
      • 什么是封装?
    • 3.访问限制机制
      • 访问限制机制是什么
      • 访问限制机制作用
      • 如何用访问限制机制?
    • 4.property装饰器
      • property 作用:
      • property 如何使用:
    • 1.多态
      • 什么是多态?
      • 多态什么用?
      • 多态的表现形式:
    • 2.抽象
      • 什么是抽象?
      • 抽象作用
      • 如何实现
    • 鸭子类型
      • 什么是鸭子类型?
      • 为什么要有鸭子类型?
      • 鸭子类型的作用?
      • 如何实现
    • 4.isinstance与issubclass
      • 如何使用:
    • 5.classmethod与staticmethod
      • classmethod:
      • staticmethod(静态方法):
      • 绑定方法:
      • classmethod:
    • 6.反射:
      • 什么是反射?
      • 语法
      • 如何使用
    • .反射
      • 1、hasattr: 查找-反射
      • 2、getattr :取值 反射
      • 3、setattr: 添加-反射
      • 4、delattr: 删除-反射
      • 5.反射应用
    • 类的内置方法(魔法方法)
      • 魔法归总
      • 1.双下new
      • 2.双下getattr
      • 3.双下getattribute
      • 4.双下setattr
      • 5.双下call
      • 6.双下str
      • 7.双下getitem
      • 8.双下setitem
      • 9.自定义比较对象大小双下:gt、lt、eq
      • 10.上下文管理双下enter进入文件时,双下__exit__离开
      • 11.双下del删除时触发
      • 12.双下__slots__优化对象内存
    • 单例
      • 单列模式分类
      • 1.classmethod类绑定单例
      • 2.双下new方法单例

面向对象编程

1.什么是面向对象编程?

面向过程编程思想

核心是 过程 二字, 过程指的是解决问题的步骤,即先干什么再干什么
基于该编程思想编写程序,就好比在设计一条工厂流水线,一种机械式的思维方式。

面向过程编程优缺点:

优点:
将复杂的问题流程化,进而简单化缺点:
牵一发而动全身,可扩展性差

面向对象编程思想

核心是 对象 二字,对象指的是 特征(属性/变量)与技能(方法/函数)的结合体。基于该编程思想编写程序,就好比在创造世界,一种上帝式的思维方式。

面向对象编程思想优缺点:

优点:
可扩展性强。(只需要关注对象能干什么拥有什么特征,无需关注他做事情的步骤)缺点:
编写的复杂难度较高于面向过程编程思想。注意: 在生产开发中,两种编程思想相辅相成,缺一不可!

2.什么是类?如何定义。

类:

类指的是类型类别。

对象

对象是 特征与技能 的结合体, 类是一系列对象相同的 特征与技能 的结合体。

要定义类时

要定义类: 先抽象,再定义。

现实世界中:

先有对象,然后再有类。

在程序中:

先定义类,后调用用类产生对象。

对象的特征和技能

       - 对象1:- 特征:- name: hcy- age: 84- sex: female- school = 'oldboy'- 技能:- 漂泊十年无需用一毛- 学习- 对象2:- 特征:- name: JP- age: 95- sex: male- school = 'oldboy'- 技能:- 澳门赌场上线首席发牌师- 学习- 学生类:- 相同的特征- school = 'oldboy'- 相同的技能- 学习class 类名:school = 'oldboy'def learn(self):print('learning...')

3.如何产生对象?

 - 调用类产生对象语法: 类名 + () 调用- 调用类的过程: 称之为类的实例化,产生的对象称之为类的一个实例。- 调用类时发生的事情:
1) 产生一个空对象的名称空间
2) 自动触发类内容__init__方法的执行。
3) 会将对象本身当做第一个参数,以及调用类括号内所有的参数并传给__init__。

代码

class Student:# 学校school = 'oldboy'def __init__(self, name, sex, age):  # stu1, 'tank', 'male', 17print(self.__dict__)  #{}# 给对象添加新的属性self.name = name  # stu1.x = 'tank'self.sex = sex  # stu1.y = 'male'self.age = age  # stu1.z = 17# 查看当前对象的名称空间print(self.__dict__)  #{'name': 'wang', 'sex': 17, 'age': 'male'}# 学习技能   ----> method ---》 方法def learn(self):print(self)  #print('learning...')# 查看类的名称空间
print(Student.__dict__)stu1 = Student('wang',17,'male')
stu1.learn()  #learning...stu1.name = '江鹏'
stu1.sex = 'female'
stu1.age = 84
print(stu1.name, stu1.sex, stu1.age)  #江鹏 female 84## 结果:
{'__module__': '__main__', 'school': 'oldboy', '__init__': <function Student.__init__ at 0x0000028C5598E3A8>, 'learn': <function Student.learn at 0x0000028C5598E9D8>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}{}{'name': 'wang', 'sex': 17, 'age': 'male'}<__main__.Student object at 0x0000028C64A07DC8>learning...江鹏 female 84

调用类时的事件:

调用类会时,自动触发__init__,然后产生一个对象,会将对象第一个参数传给—__init__,也就是self。 # self相当于就是p_obj对象
并将调用类括号中的参数一并传给__init__()class People:country = 'China'def __init__(self, name, age, sex):  # self相当于就是p_obj对象print(self.__dict__)   #{}print(self)            # <__main__.People object at 0x0000022D8C569548>self.name = nameself.age = ageself.sex = sexprint(self.__dict__) #{'name': 'tank', 'age': 17, 'sex': 'male'}# 注意: 看到self就应该知道是对象本身def learn(self):print('learning....')p_obj = People('tank', 17, 'male')
p_obj.learn() #learning....结果:
{}
<__main__.People object at 0x0000022D8C569548>
{'name': 'tank', 'age': 17, 'sex': 'male'}
learning....

4.对象属性的查找顺序:

对象名字的查找顺序:  *******1.对象.属性,会先找对象自己的。2.若对象没有,会去找类的。3.若类没有,则会报错。
class People:country = 'China'name = 'jason'def __init__(self, name, age, sex):self.name = nameself.age = ageself.sex = sexdef run(self):print('running...')obj1 = People('tank', 17, 'male')
print(obj1.name)  # tank  找对象自己的name属性
print(obj1.country)  # China  对象没有,找类中的属性# print(obj1.jason)  # 对象没有,类也没有,就会报错!
print(obj1.__dict__)
# 给对象的名称空间添加 country='中国' 属性
obj1.country = '中国'
print(obj1.__dict__)
print(People.__dict__)
print(obj1.country)

5.类内部的函数:

- 由类来调用的方法,就是一个普通函数,函数需要几个参数,就得传入几个参数。
- 由对象来调用,就是一个对象的绑定方法,由不同的对象调用就会绑定给不同的对象,称之为对象的绑定方法。

一切皆对象

比如: python的八大数据类型都是类定义数据类型的值时,内部自动调用响应的类,然后产生对象。class Foo:def __init__(self, x, y, z):self.x = xself.y = yself.z = z# 产生对象
# 调用类产生对象的过程称之为类的实例化,对象称之为类的一个实例。
foo_obj = Foo(10, 20, 30)
print(foo_obj) #<__main__.Foo object at 0x000002072717A248>

人狗大作战

需求:- 先有人类,狗类,调用人类与狗类,产生两个对象、- 一个是人对象,一个是狗对象,人狗互咬。
class People:def __init__(self, name, life, arg):self.name = nameself.life = lifeself.arg = arg# 人调用bite时,传入狗对象def bite(self, dog_obj):print(f'人:[{self.name}] 开始 咬 狗:[{dog_obj.name}]!')# 减掉狗对象中的生命值  值为人的攻击力dog_obj.life -= self.argprint(f'狗的生命值减掉: [{self.arg}], 还剩狗的血量: [{dog_obj.life}]')if dog_obj.life <= 0:print(f'狗[{dog_obj.name}]已经挂了')return True# 狗类
class Dog:def __init__(self, name, life, dog_type, arg):self.name = nameself.dog_type = dog_typeself.life = lifeself.arg = arg# 狗对象调用bite时,传入人对象def bite(self, p_obj):print(f'狗:[{self.name}] 开始 咬人:[{p_obj.name}]!')# 减掉人对象中的生命值  值为狗的攻击力p_obj.life -= self.argprint(f'人的生命值减掉: [{self.arg}], 还剩人的血量: [{p_obj.life}]')if p_obj.life <= 0:print(f'人[{p_obj.name}]已经挂了')return Truep1 = People('高弟', 2000, 500)
d1 = Dog('HCY', 2500, '哈士奇', 250)p2 = People('高弟2', 5000, 50)
import timewhile True:# 开始人狗互咬# if p1.life or d1.life:res1 = d1.bite(p2)if res1:breaktime.sleep(1)res2 = p1.bite(d1)if res2:breaktime.sleep(1)

继承

1.什么是继承?

继承是一种新建类的方式,新建的类称之为子类或派生类,
继承的类是父类,也称之为基类或超类。

2.继承的好处?

减少代码冗余(减少重复代码)

3.如何继承?

- 确认继承关系- 先抽象,再继承- 类是抽取一系列对象相似的部分- 父类是抽取一系列类相似的部分- 父类- 子类- 语法:class 子类(父类):

4.继承背景下,对象.属性的查找顺序

1.先从对象的名称空间中查找
2.若对象中没有,去子类中查找
3.若子类中没有,去父类中查找

5.派生:

派生: 子类继承父类,派生出自己的属性和方法。

6.重用父类的属性与方法,并派生出自己的属性与方法。

- 直接调用父类中__init__(self)- super().__init__()

7.新式类与经典类

- 新式类- 所以继承object的类,以及子孙类都称之为新式类。- 经典类- 没有继承object的类,都是经典类。

8.钻石继承(菱形继承)背景下,属性查找顺序

经典类: 深度优先
新式类: 广度优先

9..mro: 类的内置方法

类.mro()
super严格依赖mro继承序列的顺序

1.组合

是什么组合?

组合是一个对象中,包含另一个或多个对象。

组合的好处(作用)

减少代码冗余 (减少重复代码),提高开发效率。

组合与继承相比?

耦合度低,程序的可扩展性高。
耦合度高,程序的可扩展性低。

组合如何实现?

class User:def __init__(self, name, age, sex):self.name = nameself.age = ageself.sex = sexdef run(self):print('user running...')class Date:def __init__(self, year, month, day):self.year = yearself.month = monthself.day = daydef print_birth(self):print(self.year,self.month,self.day)user_obj = User('WH', 20, 'male')
date_obj = Date(1999, 11, 11)
user_obj.date_obj = date_objuser_obj.date_obj.print_birth()#1999 11 11

2.封装:

什么是封装?

将一堆属性与方法 封装 到对象中。
封: 比如:将袋子封起来
装:比如: 将一堆小猫、小狗、HCY装进袋子里
将一堆属性与方法 封装 到对象中。

3.访问限制机制

访问限制机制是什么

凡是在类内部定义的,以__开头的属性或方法,都不能被外部 “直接访问”。
- 若想访问: (强烈不推荐)_类名__属性/方法

访问限制机制作用

可以将隐私的数据,隐藏起来,可以让调用者通过接口来获取。
接口中可以做一些逻辑处理,限制调用者的访问
可以保证数据安全。

如何用访问限制机制?

class User:__属性 = 属性值def __方法(self):passdef inf(self):# 逻辑的处理# 用户访问的限制return self.__属性# 列题:
class ATM:# 取钱功能:# 1.插入磁卡def __insert_card(self):print('开始插卡...')pass# 2.输入密码def __input_pwd(self):print('输入密码...')pass# 3.输入取款金额def __input_bal(self):print('输入取款金额...')pass# 4.吐钱def __output_money(self):print('开始吐钱...')pass# 5.打印流水账单def __print_flow(self):print('打印流水账单...')pass# 取款顺序规范接口:def withdraw(self):# 1.插入磁卡self.__insert_card()# 2.输入密码self.__input_pwd()# 3.输入取款金额self.__input_bal()# 4.吐钱self.__output_money()# 5.打印流水账单self.__print_flow()amt_obj = ATM()
amt_obj.withdraw()

访问限制机制需注意

接口只能在 “__属性/方法” 的类中返回 “__属性/方法”。

4.property装饰器

property 作用:

可以将 def 方法() ---> 在调用时  对象.方法() -----> 对象.方法。
迷惑用户,让用户误以为调用的方法是一个属性。

property 如何使用:

        @propertydef get_name(self):return self.nameprint(obj.get_name)  # obj.get_name()# 需求: 计算人体 bmi 指数
# 体重 / 身高的平方
# value = weight / (height * height)
class User:def __init__(self, name, weight, height):self.__name = nameself.weight = weightself.height = height# 获取bmi指数方法@propertydef bmi(self):# return self.weight / (self.height * self.height)return self.weight / (self.height ** 2)@propertydef name(self):return self.__name# 了解: 设置被property装饰后的方法# 注意: 需要修改的方法名字要与被property装饰器后的方法一样# @name.setter# def name(self, value):  # '赵shuai兵' --- 》 value#     self.__name = value# @name.deleter# def name(self):  # 删除属性#      del self.__nameuser_obj = User('HCY', 100, 1.9)# user_obj.bmi()()
# print(user_obj.bmi())# user_obj.bmi()
print(user_obj.bmi)

1.多态

什么是多态?

指的是同一事物的多种形态。

多态什么用?

多态也称之为多态性,在不知道具体对象的情况下,统一对象调用相似方法的规范(名字)。

多态的表现形式:

继承

先抽象,再继承

父类:

定制一套统一的规范。

子类

遵循父类统一的规范。

遵循代码:

# 正面教材
- 动物(父类):- eat、speak、run- 猪、猫、狗(子类):- eat、speak、run# 反面教材- chi、jiao、pao
# 列:
# 动物类
class Animal:# 方法 吃def eat(self):pass# 方法 叫def speak(self):pass
# 猪类
class Pig(Animal):def eat(self):print('bia唧...')def speak(self):print('哼哼哼...')# 猫类
class Cat(Animal):def eat(self):print('咬ji 咬ji....')def speak(self):print('喵喵喵...')# 狗类
class Dog(Animal):def eat(self):print('舔 ji 舔ji...')def speak(self):print('汪汪汪...')animal1 = Dog()
animal2 = Pig()
animal3 = Cat()# 让动物们叫起来
animal1.speak()
animal2.speak()
animal3.speak()#结果
汪汪汪...
哼哼哼...
喵喵喵...

缺点:

耦合度高,程序的可扩展性低。
注意
在python中是不会强制子类必须要遵循父类的规范,所以出现了抽象类。

2.抽象

什么是抽象?

在python内置的abc模块中,有一个抽象类(abc.ABCMeta)

抽象作用

只要父类继承了抽象类
子类就必须要遵循父类的规范
父类有几个抽象方法,子类就必须有几个一摸一样的方法。
注意:
注意: 在python中不推荐使用抽象类。注意: 子类必须按照父类的方法编写规范,缺一不可。(只要父类中有几个抽象方法,子类就必须要定义几个)
'''

如何实现

import abc# 父类
class Animal(metaclass=abc.ABCMeta):# 方法 吃@abc.abstractmethoddef eat(self):pass# 方法 叫@abc.abstractmethoddef speak(self):pass
# 猪类class Pig(Animal):def run(self):passdef eat(self):print('bia唧...')def speak(self):print('哼哼哼...')pig_obj = Pig()
pig_obj.eat()  #bia唧...# 如果掉用装饰后的值就报错(不能用抽象类的方法实例化抽象类动物) 因为他只是一个模板,装饰后,子类必须遵寻父类的值,父类的值跑了子类,覆盖子类,所以掉用子类。子类就必须要遵循父类的规范,父类有几个抽象方法,子类就必须有几个一摸一样的方法。
#
# pig_obj=Animal()
# pig_obj.eat()

缺点

耦合度极高,程序可扩展性极低。

鸭子类型

什么是鸭子类型?

只要对象长得像鸭子,行为举止也像鸭子,比如: 游泳,吃鱼, 所以他就是鸭子

为什么要有鸭子类型?

2.为什么要有鸭子类型?不同对象,先抽象出相同类型的方法,给他们定制一套统一的规范。所有的类,在定义时都按照统一的规范进行编写。- 多态的三种表现形式:- 继承父类    ****- 耦合度高,程序的可扩展性低- 继承抽象类  ***- 耦合度极高,程序的可扩展性极低- 鸭子类型:   *****- 耦合度低,程序的可扩展性高注意: 在python中,强烈推荐使用鸭子类型。

鸭子类型的作用?

- 在定义类之前,先定制一套鸭子类型的规范。
- 所有开发者都按照这套规范来定义类中的方法。

优点:

耦合极低,程序的可扩展性高。

缺点:

造成了代码的冗余

如何实现

# 猪类
class Pig:def eat(self):print('bia唧...')def speak(self):print('哼哼哼...')# 猫类
class Cat:def eat(self):print('咬ji 咬ji....')def speak(self):print('喵喵喵...')# 狗类
class Dog:def eat(self):print('舔 ji 舔ji...')def speak(self):print('汪汪汪...')

4.isinstance与issubclass

isinstance:判断一个对象是否是一个类的实例。
- 如果是: True- 如果不是: False
- issubclass:判断一个子类是否是另一个类的子类。- 如果是: True- 如果不是: False

如何使用:

# isinstance:
class Foo:passclass Boo:passfoo_obj = Foo()
boo_obj = Boo()print(isinstance(foo_obj, Foo))  # True
print(isinstance(boo_obj, Foo))  # False# issubclass
class Father:passclass Sub(Father):passclass Foo:passprint(issubclass(Sub, Father))  # True
print(issubclass(Foo, Father))  # False

5.classmethod与staticmethod

classmethod:

是一个装饰器,可以装饰在类内部的方法中,将该方法变成类的绑定方法。
class Dog():def eat(self):print('狗狗吃饭饭。。。')class Pig():@classmethod  # 将此方法对象绑定def eat(self):print('猪猪看电视。。。')# 对象绑定方法,需要实例化出一个对象
keji = Dog()
keji.eat()# 类绑定方法,不需要对象,直接通过类
zhu = Pig.eat()
# 列二:进阶高级
class DB:__data = 'jeff is very handsome!!!'def __init__(self, user, pwd, role):self.user = userself.pwd = pwdself.role = role# 查看数据方法@classmethod  # 类绑定def check_db(cls, user, pwd, role):  # cls --》指的是类# 在类方法内部调用类产生一个实例 ---》 对象obj = cls(user, pwd, role)    # 再类的内部实例化出一个对象,供内部使用# 1.查看数据前,必须要通过校验if obj.user == 'tank' and obj.pwd == '123' and obj.role == 'admin':print('检验通过..')print(cls.__data)return cls.__data# 类绑定方法了
DB.check_db('tank', '123', 'admin')
#  结果:
检验通过..
jeff is very handsome!!!

staticmethod(静态方法):

是一个装饰器,可以装饰在类内部的方法中,将该方法变成非绑定方法。
1.不用非绑定方法,打印的是func函数的地址
class Foo:def func(res):print(res)
obj = Foo()
obj.func()
#  <__main__.Foo object at 0x000001FF9F5D82E8>2.对象调用非绑定方法
class Foo:@staticmethoddef func(res):print(res)
# 产生了obj对象
obj = Foo()
obj.func(123)  # 1233.类直接调用非绑定方法
class Foo:@staticmethoddef func(res):print(res)
Foo.func(1234)
#  1234

绑定方法:

对象的绑定方法:

- 对象的绑定方法: (在类内部定义(封装)一个方法即可)
由对象来调用,对象来调用,会将对象当做第一个参数传入给该方法。
class OldboyStudent:school = 'oldboy'def __init__(self, name, age, gender):self.name = nameself.age = ageself.sex = genderdef choose_course(self):print(f'{self.name} choosing course')def func(self):print('from func')stu1 = OldboyStudent('nick', 18, 'male')
stu2 = OldboyStudent('sean', 17, 'male')
stu3 = OldboyStudent('tank', 19, 'female')print(stu1.name)   # nick
print(stu1.school)   # oldboy
2.类的绑定方法@classmethod

类的绑定方法:

- 类的绑定方法:   (在类内部方法中,使用classmethod装饰器即可)
由类来调用,类来调用,会将类当做第一个参数传入给该方法。

classmethod:

是一个装饰器,可以装饰在类内部的方法中,将该方法变成类的绑定方法。
class Dog():def eat(self):print('狗狗吃饭饭。。。')class Pig():@classmethod  # 将此方法对象绑定def eat(self):print('猪猪看电视。。。')# 对象绑定方法,需要实例化出一个对象
keji = Dog()
keji.eat()# 类绑定方法,不需要对象,直接通过类
zhu = Pig.eat()
# 列二:进阶高级
class DB:__data = 'jeff is very handsome!!!'def __init__(self, user, pwd, role):self.user = userself.pwd = pwdself.role = role# 查看数据方法@classmethod  # 类绑定def check_db(cls, user, pwd, role):  # cls --》指的是类# 在类方法内部调用类产生一个实例 ---》 对象obj = cls(user, pwd, role)    # 再类的内部实例化出一个对象,供内部使用# 1.查看数据前,必须要通过校验if obj.user == 'tank' and obj.pwd == '123' and obj.role == 'admin':print('检验通过..')print(cls.__data)return cls.__data# 类绑定方法了
DB.check_db('tank', '123', 'admin')
#  结果:
检验通过..
jeff is very handsome!!!

非绑定方法:

- 非绑定方法:     (在类内部方法中,使用staticmethod装饰器即可)
由对象/类来调用,由谁来调用,它都是一个普通函数,内部需要接受几个参
class OldboyStudent:school = 'oldboy'def __init__(self, name, age, gender):self.name = nameself.age = ageself.sex = genderdef choose_course(self):print(f'{self.name} choosing course')def func(self):print('from func')stu1 = OldboyStudent('nick', 18, 'male')
stu2 = OldboyStudent('sean', 17, 'male')
stu3 = OldboyStudent('tank', 19, 'female')print(stu1.name)   # nick
print(stu1.school)   # oldboy
2.类的绑定方法@classmethod

6.反射:

什么是反射?

通过 “字符串” 对 对象的属性或方法进行操作。

语法

- hasattr: 通过 字符串 判断对象的属性或方法是否存在,存在返回True, 否则返回False。
hasattr(对象, '对象的属性或方法字符串')- getattr: 通过 字符串 获取对象的属性或方法是否存在,存在返回获取属性或方法, 否则返回报错。
getattr(对象, '对象的属性或方法字符串', '默认值')- 若设置默认值,没有则返回默认值
- setattr: 通过 字符串 设置(添加/修改)对象的属性或方法。
setattr(对象, '对象的属性或方法字符串', '属性的值')- delattr: 通过 字符串 删除 对象的属性或方法,若属性不存在,则报错。
delattr(对象, '对象的属性或方法字符串')

如何使用

# 反射应用:
class FileControl:def run(self):while True:# 让用户输入上传或下载功能的命令:user_input = input('请输入 上传(upload) 或 下载(download) 功能:').strip()# 通过用户输入的字符串判断方法是否存在,然后调用相应的方法if hasattr(self, user_input):func = getattr(self, user_input)func()else:print('输入有误!')def upload(self):print('文件正在上传...')def download(self):print('文件正在下载...')file_control_obj = FileControl()
file_control_obj.run()

.反射

反射使用场景:1.反射就是对属性的增删改查,但是如果直接使用内置的 dict来操作,语法繁琐,不好理解2.如果对象是别人提供的,判断这个对象是否满足要求hasattr(p,'name'):查找p对象中是否存在name属性
getattr(p,'name'):取值,p对象中name属性
setattr(p,'name','jeff'):添加,为p对象中添加name属性jeff
delattr(p,'name'):删除,删除p对象中name属性

1、hasattr: 查找-反射

foo_obj对象中是否存在x属性

class Foo:def __init__(self, x, y):self.x = xself.y = y
foo_obj = Foo(10, 20)
# 通过字符串x 判断对象中是否有 x属性
print(hasattr(foo_obj, 'x'))  # True
print(hasattr(foo_obj, 'z'))  # False

2、getattr :取值 反射

getattr(foo_obj,'x'):取值p对象中name属性

class Foo:def __init__(self, x, y):self.x = xself.y = yfoo_obj = Foo(10, 20)res = getattr(foo_obj, 'x')
print(res)  # 10

3、setattr: 添加-反射

为foo_obj对象中添加z属性30

class Foo:def __init__(self, x, y):self.x = xself.y = yfoo_obj = Foo(10, 20)setattr(foo_obj, 'z', 30)  # 为对象添加z属性值为30
print(hasattr(foo_obj, 'z'))  # True

4、delattr: 删除-反射

删除foo_obj对象中x属性

class Foo:def __init__(self, x, y):self.x = xself.y = yfoo_obj = Foo(10, 20)delattr(foo_obj, 'x')  # 删除对象中x属性
print(hasattr(foo_obj, 'x'))  # False

5.反射应用

通过用户输入的字符串,判断是否存在,getattr取值,加括号调用相应的功能函数

class FileControl:def run(self):while True:# 让用户输入上传或下载功能的命令:user_input = input('请输入 上传(upload) 或 下载(download) 功能:').strip()# 通过用户输入的字符串判断方法是否存在,然后调用相应的方法if hasattr(self, user_input):func = getattr(self, user_input)func()else:print('输入有误!')def upload(self):print('文件正在上传...')def download(self):print('文件正在下载...')file = FileControl()
file.run()

类的内置方法(魔法方法)

魔法归总

类的内置方法(魔法方法):凡是在类内部定义,以__开头__结尾的方法,都是类的内置方法,也称之为魔法方法。类的内置方法,会在某种条件满足下自动触发。内置方法如下:__new__: 在__init__触发前,自动触发。  调用该类时,内部会通过__new__产生一个新的对象。__init__: 在调用类时自动触发。    通过产生的对象自动调用__init__()__getattr__: 在 “对象.属性” 获取属性时,若 “属性没有” 时触发。__getattribute__: 在 “对象.属性” 获取属性时,无论 "属性有没有" 都会触发。# 注意: 只要__getattr__ 与 __getattribute__ 同时存在类的内部,只会触发__getattribute__。__setattr__:当 “对象.属性 = 属性值” , 添加或修改属性时触发__call__ : 在调用对象 “对象 + ()” 时触发。 即:对象() 或者 类()()__str__  : 在打印对象时触发。 # 注意: 该方法必须要有一个 “字符串” 返回值。__getitem__: 在对象通过 “对象[key]” 获取属性时触发。__setitem__: 在对象通过 “对象[key]=value值” 设置属性时触发。__gt__,__lt__,__eq__:自定义比较对象大小双下:gt、lt、eq__enter__:  进入文件时,开打文件时执行。返回值:self__exit__:  退出文件时,报错中断、或者代码执行完时执行。 返回值:可以有返回值,是bool类型__del__ : 手动删除时立马执行,或者程序运行结束时自动执行使用场景:当你的对象使用过程中,打开了不属于解释器的资源;例如,文件,网络端口__slots__:原理,给对象声明只有某些属性,从而删除不必要的内存,不能添加新属性使用场景:1.优化对象内存  2.限制属性数量

1.双下new

因为类继承了object,所有在调用类之前会自动先执行双下new来创建对象。这里的双下new重写了object中的双下new,所以此时不能创建出对象。
class Demo():def __new__(cls, *args, **kwargs):print('此处是__new__方法的执行')# python内部通过object调用内部的__new__实现产生一个空的对象  ---> 内存地址def __init__(self):print('此处是__init__方法的执行')
# 只是实例化对象
demo_obj = Demo()
# 结果:
此处是__init__方法的执行

2.双下getattr

双下getattr: 在 “对象.属性” 获取属性时,若 “属性没有” 时触发。
class Demo():# __getattr__: 在 “对象.属性” 获取属性时,若 “属性没有” 时触发。def __getattr__(self, item):print('此处是__getattr__方法的执行')print(item)# return 想要返回的值return 'tank is very very handsome!!!'demo_obj = Demo()
res = demo_obj.x  # 获取属性,赋值
# 打印返回值
print(res)
# 结果:
此处是__getattr__方法的执行
x
jeff is very very handsome!!!

3.双下getattribute

 # 条件: __getattribute__: 在 “对象.属性” 获取属性时,无论 "属性有没有" 都会触发。class Demo():# 条件: __getattribute__: 在 “对象.属性” 获取属性时,无论 "属性有没有" 都会触发。def __getattribute__(self, item):print(item, '<-----打印属性名字')# print(self.__dict__)# return self.__dict__[item]# 注意: 此处不能通过 对象.属性,否则会产生递归调用,程序崩溃# getattr: 内部调用了 ----> __getattribute__# return getattr(self, item)demo_obj = Demo()
demo_obj.x# 结果:
x <-----打印属性名字

4.双下setattr

# __setattr__:当 “对象.属性 = 属性值” , 添加或修改属性时触发class Demo():y = 20def __setattr__(self, key, value):print('此处是__setattr__方法的执行')print(key, value)# 循环递归,报错# self.key = valuejeff = Demo()
jeff.y = 10
# 结果:
此处是__setattr__方法的执行
y 10

5.双下call

# 注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 双下__call__ 方法的执行是由对象后加括号触发的.
# 即:对象() 或者 类()()class Demo():def __call__(self, *args, **kwargs):print('此处是__call__方法的执行')# 调用对象时返回的值return [1, 2, 3, 4, 5]def y(self):passjeff = Demo()
jeff()
# 结果:
此处是__call__方法的执行

6.双下str

# __str__  : 在打印对象时触发。 # 注意: 该方法必须要有一个 “字符串” 返回值。
# print 时内部自动调用__str__
class Demo():def __str__(self):res = '此处是__str__方法的执行'# 必须有返回值return resjeff = Demo()
print(jeff)
# 结果:
此处是__str__方法的执行

7.双下getitem

# 在对象通过 “对象[key]” 获取属性时触发。
class Demo():def __getitem__(self, item):print('此处是__getitem__方法的执行')print(item)jeff = Demo()
jeff['y']
# 结果:
此处是__getitem__方法的执行
y

8.双下setitem

# 在对象通过 “对象[key]=value值” 设置属性时触发。class Demo():def __setitem__(self, key, value):print('此处是__setitem__方法的执行')print(key, value)print(self.__dict__)self.key = value  # {'key': value}   {'key': 123}print(self.__dict__)  # jeff = Demo()
jeff['y'] = 123
# 结果:
此处是__setitem__方法的执行
y 123
{}
{'key': 123}

9.自定义比较对象大小双下:gt、lt、eq

可以利用这三个自定义比较对象:
__gt__:greater than  大于缩写
__lt__:less than  小于缩写
__eq__:equal   等于缩写
class Student(object):def __init__(self, name, height, age):self.name = nameself.height = heightself.age = age# 比较大于时触发def __gt__(self, other):return self.height > other.height# 比较小于时触发def __lt__(self, other):return self.age < other.age# 比较等于时触发def __eq__(self, other):# if self.age == other.age:  # 比较两个对象的年龄if self.age == other.age and self.height == other.height:  # 比较年龄和身高return '年龄身高一样'return '年龄身高不一样'stu1 = Student("jeff", 170, 25)
stu2 = Student("make", 170, 25)print(stu1 > stu2)
print(stu1 < stu2)
print(stu1 == stu2)

10.上下文管理双下enter进入文件时,双下__exit__离开

# __enter__:1.进入文件,开打文件时执行2.函数应该返回自己self
# __exit__:1.退出文件、报错中断、或者代码执行完时执行2.可以有返回值,是bool类型class MyOpen(object):def __init__(self, path):self.path = path# 进入文件时触发def __enter__(self):self.file = open(self.path)print("文件打开....")return self# 离开文件时触发def __exit__(self, exc_type, exc_val, exc_tb):print("文件关闭")# print(exc_type,exc_val,exc_tb)self.file.close()  # 关闭文件return Truewith MyOpen('a.txt') as f:print(f.file.readline())# f.file.readline()   # 文件已经关闭了,不能读

11.双下del删除时触发

__del__ : 执行时机:手动删除时立马执行,或者程序运行结束时自动执行使用场景:当你的对象使用过程中,打开了不属于解释器的资源;例如,文件,网络端口class A:def __init__(self, name):self.name = namedef __del__(self):print('删除时触发')# 删除时关闭def __del__(self):self.file.close()jeff = A('jeff')
del jeff
# jeff.name  # 已经删除,无法访问了

12.双下__slots__优化对象内存

slots:原理,给对象声明只有某些属性,从而删除不必要的内存,不能添加新属性1.优化对象内存2.限制属性数量__slots__案例:slots使用# 第一种:不优化内存
import sys
class Person:slots = ['name']  # 声明名称空间只有name属性def __init__(self, name):self.name = name
p = Person('jeff')print(sys.getsizeof(p))
# 结果:56# 第二种:优化内存
import sys
class Person:__slots__ = ['name']  # 声明名称空间只有name属性def __init__(self, name):self.name = name
p = Person('jeff')
print(sys.getsizeof(p))
#结果:48          #####内存减少了8

单例

单例:一个对象,多次使用相同的。节约内存空间

单例模式:指的是在确定 "类中的属性与方法" 不变时,需要反复调用该类,产生不同的对象,会产生不同的内存地址,造成资源的浪费。让所有类在实例化时,指向同一个内存地址,称之为单例模式。  ----> 无论产生多个对象,都会指向 单个 实例。- 单例的优点:节省内存空间。

单列模式分类

单例模式: (面试让你手撸,一定要背下来。)1.通过classmethod  类绑定方法2.通过装饰器实现3.通过__new__实现4.通过导入模块时实现5.通过元类实现。

1.classmethod类绑定单例

# 第一种:不用单例
# 两个不同的对象,地址不一样
class MySQL():def __init__(self, host, port):self.host = hostself.port = portdef singleton(self):passobj1 = MySQL('192.168.0.101',3306)
obj2 = MySQL('192.168.0.101',3306)
print(obj1)
print(obj2)
# 结果:
<__main__.MySQL object at 0x000001FE458A8470>
<__main__.MySQL object at 0x000001FE458A8518># 第二种:用单例
# 一个对象重复使用,指向同一个地址,节约内存
class MySQL():__instance = None  # 标识对象是否已经存在def __init__(self, host, port):self.host = hostself.port = port@classmethoddef singleton(cls, host, port):  # 单例方法if not cls.__instance:obj = cls(host,port)cls.__instance = obj# 如果__instance有值,证明对象已经存在,则直接返回该对象return cls.__instanceobj1 = MySQL.singleton('192.168.0.101',3306)
obj2 = MySQL.singleton('192.168.0.101',3306)
print(obj1)
print(obj2)
# 结果:
<__main__.MySQL object at 0x000001D2B79D8518>
<__main__.MySQL object at 0x000001D2B79D8518>

2.双下new方法单例

class Singleton(object):def __new__(cls, *args, **kwargs):if not hasattr(cls, '_instance'):res = super(Singleton, cls)cls._instance = res.__new__(cls, *args, **kwargs)return cls._instanceclass A(Singleton):passobj1 = A()
obj2 = A()
print(obj1)
print(obj2)
# 结果:
<__main__.A object at 0x000001F81A3B8518>
<__main__.A object at 0x000001F81A3B8518>

python基础 面向对象编程相关推荐

  1. Python基础-面向对象编程

    本文完全转载自廖雪峰大神的教程: 面向对象编程 面向对象编程--Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数 ...

  2. Python 基础--面向对象编程

    在至今我们编写的所有程序中,我们曾围绕函数设计我们的程序,也就是那些能够处理数据的代码块.这被称作*面向过程(Procedure-oriented)*的编程方式.还有另外一种组织起你的程序的方式,它将 ...

  3. python基础——面向对象的程序设计

    python基础--面向对象的程序设计 1 什么是面向对象的程序设计 面向过程的程序设计的核心是过程,过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西. 优 ...

  4. python用类名直接调用方法_一文读全 Python 的面向对象编程方法

    背景介绍: Python 支持三种形式的编程,分别是:"命令式"."函数式"和"面向对象式". 很多优秀的开源 Python 项目里都用到了 ...

  5. python基础—面向对象

    python基础-面向对象 面向对象 面向过程VS面向对象 类和实例 实例变量和类变量 类的方法 实例方法 静态方法 类方法 面向对象的组合用法 封装.继承和多态 封装 继承 派生 方法的重写 继承注 ...

  6. 零基础入门学习Python(35)面向对象编程

    self是什么? Python的self相当于C++的this指针 由同一个类可以生成无数对象,当一个对象的方法被调用的时候,对象会将自身的引用作为第一个参数传给该方法,Python就知道要操作哪个对 ...

  7. python中面向对象编程简称为_Python基础-面向对象编程

    本文完全转载自廖雪峰大神的教程: 面向对象编程--Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的 ...

  8. python 面向对象编程简称_Python基础-面向对象编程

    简介 三中编程范式 面向过程编程 函数式编程 面向对象编程 面向对象和面向过程对比 面向过程 优点: 性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机.嵌入式开发.Lin ...

  9. Python设计模式面向对象编程

    前言 本篇文章是基于极客时间王争的<设计模式之美>做的总结和自己的理解.   说到面向对象编程,作为一个合格的Pythoner,可以说信手拈来.毕竟在Python里"万物都是对象 ...

最新文章

  1. java压测请求线程数_程序员撕开京东 618 大促压测的另一面 | 原力计划
  2. tf.nn.sparse_softmax_cross_entropy_with_logits()与tf.nn.softmax_cross_entropy_with_logits的差别
  3. 作业四:产品同质化问题
  4. [PAT乙级]1047 编程团体赛
  5. 2014创新工场校招笔试题及参考答案
  6. 以孩子兄弟链表为存储结构,请设计递归算法求树的高度
  7. 云存储应用是视频监控系统发展的必然需求
  8. python批量从pdf中转换图片保存
  9. 2017CCPC哈尔滨 M:Geometry Problem(随机)
  10. Restful规范-开发api接口
  11. Android 对话框用法
  12. java 入门面试题
  13. IE兼容/IE5兼容踩过的坑
  14. MATLAB求二阶隐函数导数,matlab隐函数求导
  15. (转)iOS 上的相机捕捉
  16. 安川机器人怎样与变位器编程_基于CAM Function的安川机器人弧焊焊接离线编程与离线仿真...
  17. 渲染TA实战:三方向映射 UE4
  18. SWF (Simple Workflow Service)简介
  19. js折线图设置y轴刻度_d3.js实现自定义多y轴折线图
  20. 刘氏广传公家族七公子巨波公后裔V0.2

热门文章

  1. Linux之禅道安装
  2. Python入门进阶:68 个 Python 内置函数详解
  3. 关于滚动条内子控件控制问题
  4. python产品质量分析报告范文_Python Jinja2 徒手生成数据分析报告
  5. 新手看过来----讨厌的运算符
  6. 快速学会linux上的chrony服务
  7. ECS实例及阿里云服务器ECS功能组件的说明
  8. 计算机在线考试word,大学计算机考试word试题及答案.docx
  9. win32画窗体背景
  10. linux rar文件怎么解压_Linux下rar压缩包的解压方法