类和对象
公有属性
"""类和对象(公有)"""
class God:
occupation = "神"
character = "善良"
def __init__(self, name, grade):
self.name = name
self.grade = grade
def infomation(self):
print("神级强者 [%s] 的修炼等级为 [%s]" % (self.name, self.grade))
obj_1 = God("唐三", 150)
obj_2 = God("马红俊", 110)
obj_1.infomation()
私有属性
"""类和对象(私有)"""
class Movie:
__stuff = '电影'
__the_style = '抗日神剧'
def __init__(self, name, public_time):
self.__name = name
self.__time = public_time
def __infomation(self):
print(f"""
物品:{Movie.__stuff}
类型:{Movie.__the_style}
名称:{self.__name}
发布时间:{self.__time}
""")
def __change(self):
dict_info = {
'0': '取消修改',
'1': '名称',
'2': '发布时间'
}
while True:
for i in dict_info:
print(f"{i}:{dict_info[i]}")
func_num = input('请输入功能号>>>')
if func_num == '0':
return
elif func_num == '1':
self.__name = input('修改名称为:').strip()
return
elif func_num == '2':
self.__time = input('修改时间为:').strip()
return
else:
print('请输入正确的功能号!')
def get(self):
print('可执行的功能')
dict_info = {
'0': '退出',
'1': '修改信息',
'2': '查看信息'
}
while True:
for i in dict_info:
print(f"{i}:{dict_info[i]}")
func_num = input('请输入功能号>>>')
if func_num == '0':
return
elif func_num == '1':
self.__change()
return
elif func_num == '2':
self.__infomation()
return
else:
print('请输入正确的功能号!')
movie_1 = Movie('黑狐', 2016)
movie_2 = Movie('铁血使命', 2013)
"""下面是使用对象的部分"""
movie_1.get()
@property
"""类和对象(将一个属性转化为一个方法时候,可以在方法上面加一个@property装饰器)"""
"""
例如,定义一个矩形类,
并定义用 @property 修饰的方法操作类中的 area 私有属性,
代码如下:
"""
class Rect:
def __init__(self, area):
self.__area = area
@property
def area(self):
return self.__area
obj_1 = Rect(10)
print(obj_1.area)
"""
小结:
以"."点的形式调用,不知道的人还以为它是"属性",但其实它是"方法"
而又因为"方法"的"封装"特性,所以数据被"神不知鬼不觉的保护起来了"
例如,某个"菜鸡黑客"以为它是"属性",想通过" obj_1.area = 60 "这语句
对数据进行篡改,但他惊讶的发现,既然失效了?他很困惑,但我们却都明白
这个所谓的 obj_1.area 根本就不是属性,而是经过伪装的"方法(函数)"
"""
class Rect_ordinary:
def __init__(self, area):
self.__area = area
def area(self):
return self.__area
obj_2 = Rect_ordinary(10)
print(obj_2.area())
"""
小结:
这种方式,菜鸡黑客一眼看穿它是"方法"而不是属性,
所以,他会立刻寻找其他方法进行数据篡改,
而不是一脸懵逼的思考为什么直接篡改不了
"""
"""总结"""
增删改查
"""类和对象("读" "改" "删")"""
class Human():
def __init__(self, age):
self.__age = age
@property
def age(self):
return f"年龄>>>{self.__age}"
@age.setter
def age(self, new_age):
if type(new_age) is not int:
raise "数据错误! 请传入int数据类型!"
if not 0 <= new_age <= 150:
raise "数据错误!请输入0~150范围的数据!"
self.__age = new_age
@age.deleter
def age(self):
del self.__age
print("已删除")
obj_1 = Human(18)
"""调用对象功能"""
print(obj_1.age)
obj_1.age = 10
print(obj_1.age)
del obj_1.age
类方法
"""类方法"""
class Hero:
# 实例方法————之构造方法
def __init__(self, age):
self.__age = age
# 实例方法————之读取年龄方法
def info(self):
return self.__age
# 类方法
@classmethod
def creat_obj(cls, age):
obj_new = cls(age)
return obj_new
# 静态方法(对象和类都可以调用它,而且也没有了自动传参的效果了)
@staticmethod
def func():
print("我是个静态方法,跟放到'类'外面的普通函数没什么区别")
# 创建对象
obj_1 = Hero(188)
"""执行部分"""
# 调用对象的---实例方法---info()
print(obj_1.info())
# 调用Hero类的---类方法---create_obj()
print(Hero.creat_obj(666).info())
# 调用---静态方法
obj_1.func()
Hero.func()
继承
"""继承"""
class Human:
star = 'earth'
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
class Chinese(Human):
nation = 'China'
def speak_chinese(self):
print(f"{self.name}正在说普通话")
def __init__(self, name, age, gender, money):
Human.__init__(self, name, age, gender)
self.money = money
class American(Human):
nation = 'America'
def speak_English(self):
print(f'{self.name}正在说英语')
dy_obj = Chinese('董永', 18, "男", 1000)
dy_obj.speak_chinese()
print(dy_obj.star)
print(dy_obj.nation)
MixIns 机制
"""MixIns机制"""
class Fowl:
pass
class SwimMixIn:
def swimming(self):
pass
class Chicken(Fowl):
pass
class Duck(SwimMixIn, Fowl):
pass
class Goose(SwimMixIn, Fowl):
pass
super
"""super()方法---是用于调用父类的一个方法"""
"""
首先提一下,新式类和经典类:
新式类都从object继承,经典类不需要
super只能用在新式类里面,不能用在经典类
super() 是用来解决"多重继承"问题的
当子类继承多个父类时候,先查找哪个父类??
通过 "类名.mro" 可以查看super的调用表
此表是根据某算法得出---解决了查找问题
super()函数的用法:
以下面的代码为例
super(Chinese, self).__init__()
1.根据mro的调用表查找--输入的"chinese类"后面的类是什么[而输入的self一般不变]
2.super-->将它下一个类返回(假设chinese类的下一个类是A类,则返回A类)
3.A类.__init__() ---> 调用 它的__init__()方法
补充:
如果在Human类中,要写 super(Human, self).xxx
可以直接使用 super().xxx (简写模式,但这种写法仅在 Python 3 中支持)
"""
# 父类
class Human:
star = "earth"
def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender
# 子类(1)
class Chinese(Human):
nation = "China"
def speak_chinese(self):
print(f"{self.name}正在说普通话")
def __init__(self, name, age, gender, money):
super(Chinese, self).__init__(name, age, gender)
self.money = money
# 子类(2)
class American(Human):
nation = "America"
def speak_English(self):
print(f'{self.name}正在说英语')
# 实例化对象
dy_obj = Chinese('董永', 18, "男", 1000)
# 调用部分
print(Chinese.mro())
多态
"""多态"""
class Car:
def run(self):
print("开始跑", end=' ')
class Benz(Car):
def run(self):
super().run()
print('加98号汽油')
class Lx(Car):
def run(self):
super().run()
print("充电")
class Auto(Car):
def run(self):
super().run()
print("加92号汽油")
# 实例化:造三台汽车
car1 = Benz()
car2 = Lx()
car3 = Auto()
car1.run()
car2.run()
car3.run()
print('\n', Benz.mro())
反射
"""反射"""
""" 反射机制---"判断" "读取" "修改" "删除" XXX的属性"""
"""
补充:
getattr(obj, 'name', False) 它可以传3个参数
如果 obj 没有 ’name‘ 这个属性
它将返回--->我们指定的’第三个参数‘
在本例中,它会返回 False
"""
class Hero():
def __init__(self, name):
self.name = name
obj = Hero("yexun")
print(hasattr(obj, 'name'))
print(getattr(obj, 'name'))
setattr(obj, 'name', 'I am not yexun again!')
print(obj.name)
delattr(obj, 'name')
print(obj.__dict__)
"""反射的具体案例:(体验一下它的魅力)"""
class Ftp:
def put(self):
print('正在上传数据...')
def get(self):
print('正在下载数据...')
def warning(self):
print('此功能不存在!')
def use(self):
option = input('请输入功能>>>')
getattr(self, option, self.warning)()
obj_new = Ftp()
while True:
s = input("\nQ退出>>>").strip()
if s == "Q" or s == "q":
break
obj_new.use()
其他方法
"""
__str__方法(可以实现 print(对象) 得到一个自定义的值)
注意!使用这个函数必须要有"字符类型"的返回值!
"""
""" 1.普通打印对象 """
class Human:
def __init__(self, name):
self.name = name
# 实例化对象
obj_1 = Human("Xiao_Ming")
# 打印对象,得到的是它的内存空间的地址
print(obj_1)
""" 2.使用__str__"改变"打印对象的效果 """
class Hero:
def __init__(self, name):
self.name = name
def __str__(self):
return "哈哈哈"
# 实例化对象
obj_2 = Hero("Peter")
# 打印对象,得到的是__str__的返回值
print(obj_2)
""" __ del__方法 """
# 通常,它是程序运行完之后,需要释放内存空间,才运行__del__方法。也就需要删除对象
# 除非,你在程序过程中调用了它,它就会执行
补充内容
# class People:
# def __init__(self, name):
# self.__name = name
#
# def name(self):
# return self.__name
#
# name666 = property(name)
#
#
# obj = People('yexun')
# print(obj.name666)
# class People:
# def __init__(self, name):
# self.__name = name
#
# @property
# def name(self):
# return self.__name
#
#
#
# obj = People('yexun')
# print(obj.name)
# class People:
# def __init__(self, name):
# self.__name = name
#
# def get_name(self):
# return self.__name
#
# def set_name(self, name):
# self.__name = name
#
# def del_name(self):
# print('del error')
#
# name123 = property(get_name, set_name, del_name)
#
#
# obj = People('yexun')
# print(obj.name123)
# obj.name123 = '王强'
# print(obj.name123)
# del obj.name123
class People:
def __init__(self, name):
self.__name = name
@property
def name123(self):
return self.__name
@name123.setter
def name123(self, name):
self.__name = name
@name123.deleter
def name123(self):
print('del error')
obj = People('yexun')
print(obj.name123)
obj.name123 = '王强'
print(obj.name123)
del obj.name123
# class People:
# def __init__(self, name, age, sex):
# self.name = name
# self.age = age
# self.sex = sex
#
# def f1(self):
# print(self.name)
#
#
# class Teacher(People):
# def __init__(self, name, age, sex, level, salary):
# People.__init__(self, name, age, sex)
# self.level = level
# self.salary = salary
#
#
# obj = Teacher('yexun', 18, 'male', 10, 3000)
# print(obj.__dict__)
class People:
def __init__(self, name, age, sex):
self.name = name
self.age = age
self.sex = sex
def f1(self):
print(self.name)
class Teacher(People):
def __init__(self, name, age, sex, level, salary):
# 在Python3 中直接写super().__init__...即可达到同样的效果
super(Teacher, self).__init__(name, age, sex)
self.level = level
self.salary = salary
obj = Teacher('yexun', 18, 'male', 10, 3000)
print(obj.__dict__)
print(Teacher.mro())
print(isinstance(obj, Teacher)) # 判断对象是否为该类的实例
# '我爱你'.__repr__() # 交互
造类
认识元类
"""造类"""
"""定制一个Human类"""
class_name = 'Human'
class_bases = (object,)
class_dict = {}
class_body = """
def __init__(self, name, age):
self.name = name
self.age = age
def scan_age(self):
print(self.name, "年龄:", self.age)
"""
exec(class_body, {}, class_dict)
abc = type(class_name, class_bases, class_dict)
print(abc)
person = abc('Xiao Ming', 18)
person.scan_age()
自定义元类
"""造类"""
"""
1.
class Human(Father) 等价于 class Human(Father, metaclass=type)
元类放到最后,Human类
最后面的参数 metaclass=type的意思是
默认使用内置的元类---"type"
"""
"""
2.
如果类定义了__call__方法,那么它的实例可以变为可调用对象
调用方式>>> 对象() # 像函数一样
"""
"""
网络编程.
__new__方法先被调用,返回一个实例对象,接着 __init__ 被调用
__new__方法的返回值就是类的实例对象,
这个实例对象会传递给 __init__ 方法中定义的 self 参数,
以便实例对象可以被正确地初始化
如果 __new__ 方法不返回值(或者说返回 None)
那么 __init__ 将不会得到调用,这个也说得通,
因为实例对象都没创建出来,调用 init 也没什么意义
__init__方法负责对象的初始化,系统执行该方法前,
其实该对象已经存在了,要不然初始化什么东西呢?
"""
"""
4.
自定义一个类 ----> 使用 ----> 得到"初始化的对象"(可进一步使用对象的属性和方法)
自定义一个元类 ----> 使用 ----> 得到"初始化的类"
"""
"""
5.
class Myselftpye(type):
# 一个能造"空对象"的新工厂(自己的__new__) == 底层的原始工厂(官方的__new__) + 自己添点东西
def __new__(cls, *args, **kwargs):
# Python 网络编程 可以使用直接使用 super().__new__ 代替 super(Class, self).__new__
return super().__new__(cls, *args, **kwargs)
# 将"空对象"进行初始化加工
def __init__(self, name, bases, dic):
if "_" in name:
raise NameError("类名不能有下划线")
if not dic.get('__doc__'):
raise SyntaxError('定义类必须写注释')
# 它的实例可以变为可调用对象:
# 例如当self为Human时候,使用"Human()"就会执行下面的代码
def __call__(self, *args, **kwargs):
...
"""
"""
下面这个自定义元类 Mytpye 是在"继承"了官方的元类 type 的基础上
对__call__这个方法进行了'个性化重造'
"""
class Mytpye(type):
def __call__(self, *args, **kwargs):
cls_obj = self.__new__(self)
self.__init__(cls_obj, *args, **kwargs)
class Human(object, metaclass=Mytpye):
def __new__(cls, *args, **kwargs):
obj = object.__new__(cls)
return obj
def __init__(self, name):
self.name = name
obj_1 = Human("XiaoMing")
使用元类
"""造类"""
"""
查看当前对象的属性
print(obj.__dict__)
为了方便用户查看类中包含哪些属性,
Python 类提供了 __dict__ 属性。
需要注意的一点是,该属性可以用类名或者类的实例对象来调用,
用类名直接调用 __dict__,会输出该由类中所有类属性组成的字典;
而使用类的实例对象调用 __dict__,会输出由类中所有实例属性组成的字典。
"""
class Base(type):
def __call__(self, *args, **kwargs):
obj = self.__new__(self)
self.__init__(obj, *args, **kwargs)
dict_new = {}
for key in obj.__dict__:
dict_new[f"YX_{key}"] = obj.__dict__[key]
obj.__dict__ = dict_new
return obj
class Human(object, metaclass=Base):
def __new__(cls, *args, **kwargs):
obj = object.__new__(cls)
return obj
def __init__(self, name, age):
self.name = name
self.age = age
def info(self):
print("姓名>>>%s\n年龄>>>%d" % (self.YX_name, self.YX_age))
person = Human("Peter", 220)
print(person.__dict__)
person.info()
print(Human.__dict__)
单例模式
前三种方法
"""
单例模式【实现方法有以下的6种】
1.模块
2.类装饰器
3.类绑定方法
4.__new__方法
5.元类
6.并发
"""
"""
A.创建一个新的Python文件
B.在这个文件里面写入以下代码:
class Human:
def __init__(self, name, age):
self.name = name
self.age = age
obj = Human('Xiao Ming', 18)
3.在另一个Python文件中写入以下代码:
from settings import obj
from settings import obj
from settings import obj
# 不论导入多少次模块,都是同一个对象
# 即:实现了单例的模式
"""
from functools import wraps
def singleton_mode(cls):
obj = None
@wraps(cls)
def wrapper(*args, **kwargs):
nonlocal obj
if not obj:
obj = cls(*args, **kwargs)
return obj
return wrapper
@singleton_mode
class Human:
def __init__(self, name, age):
self.name = name
self.age = age
obj_1 = Human('Xiao Ming', 90)
print(obj_1.name123, obj_1.age)
obj_2 = Human('Zhang San', 20)
print(obj_2.name123, obj_2.age)
print(obj_2 is obj_1)
后三种方法