一.面向对象
1.先来定义模子,用来描述一类事物,具有相同的属性和动作
class Person: #类名
def __init__(self,name,sex,job): #必须叫__init__这个名字,不能改变,所有的在一个具体的人物出现之后的拥有的属性l;'
self.men.name=name
self.sex=sex
self.job = job
alex = Person('alex','不详','搓澡工')
#alex就是对象
#alex = Person()的过程 是通过类获取一个对象的过程 - 实例化
# Person是一个类 :alex wusir都是这个类的对象
# 类有一个空间,存储的是定义在class中的所有名字
# 每一个对象又拥有自己的空间,通过对象名.__dict__就可以查看这个对象的属性和值
class 类名:
def __init__(self,参数1,参数2):
self.对象的属性1 = 参数1
self.对象的属性2 = 参数2
def 方法名(self):pass
def 方法名2(self):pass
对象名 = 类名(1,2) #对象就是实例,代表一个具体的东西
#类名() : 类名+括号就是实例化一个类,相当于调用了__init__方法
#括号里传参数,参数不需要传self,其他与init中的形参一一对应
#结果返回一个对象
对象名.对象的属性1 #查看对象的属性,直接用 对象名.属性名 即可
对象名.方法名() #调用类中的方法,直接用 对象名.方法名() 即可
类名()会自动调用类中___init__方法
2.属性的操作
print(alex.name) # print(alex.__dict__['name']) 属性的查看
alex.name = 'alexsb' # 属性的修改
alex.money = 1000000 # 属性的增加
del alex.money # 属性的删除
3.类和对象的关系
类 是一个大范围 是一个模子 它约束了事物有哪些属性 但是不能约束具体的值
对象 是一个具体的内容 是模子的产物 它遵循了类的约束 同时给属性赋上具体的值
4.实例化经历的步骤
1.类名() 之后的第一个事儿 :开辟一块儿内存空间
2.调用 init 把空间的内存地址作为self参数传递到函数内部
3.所有的这一个对象需要使用的属性都需要和self关联起来
4.执行完init中的逻辑之后,self变量会自动的被返回到调用处(发生实例化的地方)
5.类的方法使用
class Person: # 类名
def __init__(self,n=[],sex,job,hp,weapon,ad):
# 必须叫__init__这个名字,不能改变的,所有的在一个具体的人物出现之后拥有的属性
self.name = n # 对象的属性/实例变量
self.sex = sex
self.hp = hp
self.ad = ad
def 搓(self,dog): # 方法,又有一个必须传的参数-->self对象
dog.hp -= self.ad
print('%s给%s搓了澡,%s掉了%s点血,%s当前血量%s'%(self.name,dog.dog_name,
dog.dog_name,self.ad,dog.dog_name,dog.hp))
6.类的成员和命名空间
class A:
Country = '中国' # 静态变量/静态属性 存储在类的命名空间里的
def __init__(self,name,age,country): # 绑定方法 存储在类的命名空间里的
self.name = name
self.age = age
def func1(self):
print(self)
def func2(self):pass
def func3(self):pass
def func4(self):pass
def func5(self):pass
a = A('alex',83,'印度')
b = A('wusir',74,'泰国人')
A.Country = '日本人'
print(a.Country)
print(b.Country)
print(A.Country)
# 命名空间
# 在类的命名空间里 : 静态变量 绑定方法
# 在对象的命名空间里 : 类指针 对象的属性(实例变量)
# 调用的习惯
# 类名.静态变量
# 对象.静态变量 (对象调用静态变量的时候,不能对变量进行赋值操作 对象.静态变量 = 1UI27)
# 绑定方法
# 对象.绑定方法()
# 对象.实例变量
# 组合
# 一个类的对象是另一个类对象的属性
# 两个类之间 有 什么有什么的关系 : 班级有学生 学生有班级 班级有课程 图书有作者 学生有成绩
类中的变量是静态变量,
对象中的变量只属于对象本身,每个对象都有属于自己的空间来储存对象的变量,
当使用对象名去调用某一个属性的时候会优先在自己的空间寻找,找不到再去对应的类中寻找,
如果自己没有就引用类的,类也没有就报错
对于类来说,类中的变量所有的对象都是可以读取的,并且读取的是同一份变量
# 实现一个类,能够自动统计这个类实例化了多少个对象
class A:pass
A.Country = 123 # 属性的增加
print(A.Country) # 查看或者引用
class A:
count = 0
def __init__(self):
A.count += 1
a1 = A()
print(a1.count)
a2 = A()
print(A.count)
# 类中的静态变量的用处
# 如果一个变量 是所有的对象共享的值,那么这个变量应该被定义成静态变量
# 所有和静态变量相关的增删改查都应该使用类名来处理
# 而不应该使用对象名直接修改静态变量
实例化对象未被引用内存地址为同一个,实例
class Person:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def __hash__(self):
return hash(self.name+self.sex)
def __eq__(self, other):
if self.name == other.name and self.sex == other.sex:return True
p_lst = []
for i in range(84):
# print(id(Person('egon',i,'male')))
# p_lst.append(Person('egon', i, 'male'))
a = Person('egon',i,'male')
print(id(a))
p_lst.append(a)
7.组合
组合:一个类的对象是另外一个类对象的属性
# 学生类
# 姓名 性别 年龄 学号 班级 手机号
# 班级信息
# 班级名字
# 开班时间
# 当前讲师
# class Student:
# def __init__(self,name,sex,age,number,clas,phone):
# self.name = name
# self.sex = sex
# self.age = age
# self.number = number
# self.clas = clas
# self.phone = phone
# class Clas:
# def __init__(self,cname,begint,teacher):
# self.cname = cname
# self.begint = begint
# self.teacher = teacher
# 查看的是大壮的班级的开班日期是多少
# 查看的是雪飞的班级的开班日期是多少
# py22 = Clas('python全栈22期','2019-4-26','小白')
# py23 = Clas('python全栈23期','2019-5-28','宝元')
# 大壮 = Student('大壮','male',18,27,py23,13812012012)
# 雪飞 = Student('雪飞','male',18,17,py22,13812012013)
# print(大壮.clas,py23)
# print(py23.begint)
# print(大壮.clas.begint)
# 练习 :
# 对象变成了一个属性
# 班级类
# 包含一个属性 - 课程
# 课程
# 课程名称
# 周期
# 价格
# 创建两个班级 linux57
# 创建两个班级 python22
# 查看linux57期的班级所学课程的价格
# 查看python22期的班级所学课程的周期
class Clas:
def __init__(self,cname,begint,teacher):
self.cname = cname
self.begint = begint
self.teacher = teacher
class Course:
def __init__(self,name,period,price):
self.name = name
self.period = period
self.price = price
py22 = Clas('python全栈22期','2019-4-26','小白')
linux57 = Clas('linux运维57期','2019-3-27','李导')
linux58 = Clas('linux运维58期','2019-6-27','李导')
python = Course('python','6 months',21800)
linux = Course('linux','5 months',19800)
py22.course = python
linux57.course = linux
linux58.course = linux
print(py22.course.period)
print(linux57.course.price)
linux.price = 21800
print(linux57.course.price)
print(linux58.course.price)
# class Clas:
# def __init__(self,cname,begint,teacher,cprice,cperiod):
# self.cname = cname
# self.begint = begint
# self.teacher = teacher
# self.cprice = cprice # 课程价格
# self.cperiod = cperiod # 课程周期
# linux57 = Clas('linux运维57期','2019-3-27','李导',19800,'5 months')
# linux58 = Clas('linux运维58期','2019-3-27','李导',19800,'5 months')
# linux59 = Clas('linux运维59期','2019-3-27','李导',19800,'5 months')
# linux60 = Clas('linux运维60期','2019-3-27','李导',19800,'5 months')
# linux61 = Clas('linux运维51期','2019-3-27','李导',19800,'5 months')
# linux57.cprice = 21800
# linux58.cprice = 21800
8.继承
___需要解决代码的重复
class A:
pass
class B(A):
pass
# B继承A,A是父类,B是子类
# A是父类 基类 超类
# B是子类 派生类
子类可以使用父类中的 : 方法 静态变量
class Animal:
def __init__(self,name):
self.name = name
def eat(self):
print('%s is eating'%self.name)
def drink(self):
print('%s is drinking'%self.name)
def sleep(self):
print('%s is sleeping'%self.name)
class Cat(Animal):
def climb_tree(self):
print('%s is climbing'%self.name)
class Dog(Animal):
def house_keep(self):
print('%s house keeping'%self.name)
小白 = Cat('小白')
# 先开辟空间,空间里有一个类指针-->指向Cat
# 调用init,对象在自己的空间中找init没找到,到Cat类中找init也没找到,
# 找父类Animal中的init
# 当子类和父类的方法重名的时候,我们只使用子类的方法,而不会去调用父类的方法了
# 子类想要调用父类的方法的同时还想执行自己的同名方法
# 猫和狗在调用eat的时候既调用自己的也调用父类的,
# 在子类的方法中调用父类的方法 :父类名.方法名(self)
class Animal:
def __init__(self,name,food):
self.name = name
self.food = food
self.blood = 100
self.waise = 100
def eat(self):
print('%s is eating %s'%(self.name,self.food))
def drink(self):
print('%s is drinking'%self.name)
def sleep(self):
print('%s is sleeping'%self.name)
class Cat(Animal):
def eat(self):
self.blood += 100
Animal.eat(self)
def climb_tree(self):
print('%s is climbing'%self.name)
self.drink()
class Dog(Animal):
def eat(self):
self.waise += 100
Animal.eat(self)
def house_keep(self):
print('%s is keeping the house'%self.name)
小白 = Cat('小白','猫粮')
小黑 = Dog('小黑','狗粮')
小白.eat()
小黑.eat()
print(小白.__dict__)
print(小黑.__dict__)
# 继承语法 class 子类名(父类名):pass
# 父类和子类方法的选择:
# 子类的对象,如果去调用方法
# 永远优先调用自己的
# 如果自己有 用自己的
# 自己没有 用父类的
# 如果自己有 还想用父类的 : 直接在子类方法中调父类的方法 父类名.方法名(self)
# 单继承 只有一个爹
# 调子类的 : 子类自己有的时候
# 调父类的 : 子类自己没有的时候
# 调子类和父类的 :子类父类都有,在子类中调用父类的
# 多继承 有多个爹
# 一个类有多个父类,在调用父类方法的时候,按照继承顺序,先继承的就先寻找
继承分为经典类和新式类
# 只要继承object类就是新式类
# 不继承object类的都是经典类
# python3 所有的类都继承object类,都是新式类
# 在py2中 不继承object的类都是经典类
# 继承object类的就是新式类了
# 经典类 :在py3中不存在,在py2中不主动继承object的类
# 在py2中
# class A:pass # 经典类
# class B(object):pass # 新式类
# 在py3中
# class A:pass # 新式类
# class B(object):pass # 新式类
# 在单继承方面(无论是新式类还是经典类都是一样的)
# class A:
# def func(self):pass
# class B(A):
# def func(self):pass
# class C(B):
# def func(self):pass
# class D(C):
# def func(self):pass
# d = D()
# 寻找某一个方法的顺序:D->C->B->A
# 越往父类走,是深度
# 多继承
class A:
def func(self):
print('A')
class B(A):
pass
# def func(self):
# print('B')
class C(A):
pass
# def func(self):
# print('C')
class D(B,C):
pass
# def func(self):
# print('D')
print(D.mro()) # 只在新式类中有,经典类没有的
# d = D()
# d.func()
# 在走到一个点,下一个点既可以从深度走,也可以从广度走的时候,总是先走广度,再走深度,广度优先
# 在经典类中,都是深度优先,总是在一条路走不通之后再换一条路,走过的点不会再走了
# C3算法
# A(O) = [AO]
# B(A) = [BAO]
# C(A) = [CAO]
# D(B) = [DBAO]
# E(C) = [ECAO]
# F(D,E) = merge(D(B) + E(C))
# = [F] + [DBAO] + [ECAO]
# F = [DBAO] + [ECAO]
# FD = [BAO] + [ECAO]
# FDB = [AO] + [ECAO]
# FDBE = [AO] + [CAO]
# FDBEC= [AO] + [AO]
# FDBECA= [O] + [O]
# FDBECAO
# 算法的内容
# 如果是单继承 那么总是按照从子类->父类的顺序来计算查找顺序
# 如果是多继承 需要按照自己本类,父类1的继承顺序,父类2的继承顺序,...
# merge的规则 :如果一个类出现在从左到右所有顺序的最左侧,并且没有在其他位置出现,那么先提出来作为继承顺序中的一个
# 或 一个类出现在从左到右顺序的最左侧,并没有在其他顺序中出现,那么先提出来作为继承顺序中的一个
# 如果从左到右第一个顺序中的第一个类出现在后面且不是第一个,那么不能提取,顺序向后继续找其他顺序中符合上述条件的类
# 经典类 - 深度优先 新式类 - 广度优先
# 深度优先要会看,自己能搞出顺序来
# 广度优先遵循C3算法,要会用mro,会查看顺序
# 经典类没有mro,但新式类有
9.抽象类多态和鸭子类型
# 普通的类
# 抽象类 是一个开发的规范 约束它的所有子类必须实现一些和它同名的方法
# 支付程序
# 微信支付 url连接,告诉你参数什么格式
# {'username':'用户名','money':200}
# 支付宝支付 url连接,告诉你参数什么格式
# {'uname':'用户名','price':200}
# 苹果支付
# class Payment: # 抽象类
# def pay(self,money):
# '''只要你见到了项目中有这种类,你要知道你的子类中必须实现和pay同名的方法'''
# raise NotImplementedError('请在子类中重写同名pay方法')
#
# class Alipay(Payment):
# def __init__(self,name):
# self.name = name
# def pay(self,money):
# dic = {'uname':self.name,'price':money}
# # 想办法调用支付宝支付 url连接 把dic传过去
# print('%s通过支付宝支付%s钱成功'%(self.name,money))
#
# class WeChat(Payment):
# def __init__(self,name):
# self.name = name
# def pay(self,money):
# dic = {'username':self.name,'money':money}
# # 想办法调用微信支付 url连接 把dic传过去
# print('%s通过微信支付%s钱成功'%(self.name,money))
#
# class Apple(Payment):
# def __init__(self,name):
# self.name = name
# def pay(self,money):
# dic = {'name': self.name, 'number': money}
# # 想办法调用苹果支付 url连接 把dic传过去
# print('%s通过苹果支付%s钱成功' % (self.name, money))
# aw = WeChat('alex')
# aw.pay(400)
# aa = Alipay('alex')
# aa.pay(400)
# 归一化设计
# def pay(name,price,kind):
# if kind == 'Wechat':
# obj = WeChat(name)
# elif kind == 'Alipay':
# obj = Alipay(name)
# elif kind == 'Apple':
# obj = Apple(name)
# obj.pay(price)
#
# pay('alex',400,'Wechat')
# pay('alex',400,'Alipay')
# pay('alex',400,'Apple')
# appa = Apple('alex')
# appa.fuqian(500)
# 实现抽象类的另一种方式,约束力强,依赖abc模块
# from abc import ABCMeta,abstractmethod
# class Payment(metaclass=ABCMeta):
# @abstractmethod
# def pay(self,money):
# '''只要你见到了项目中有这种类,你要知道你的子类中必须实现和pay同名的方法'''
# raise NotImplementedError('请在子类中重写同名pay方法')
#
# class Alipay(Payment):
# def __init__(self,name):
# self.name = name
# def pay(self,money):
# dic = {'uname':self.name,'price':money}
# # 想办法调用支付宝支付 url连接 把dic传过去
# print('%s通过支付宝支付%s钱成功'%(self.name,money))
#
# class WeChat(Payment):
# def __init__(self,name):
# self.name = name
# def pay(self,money):
# dic = {'username':self.name,'money':money}
# # 想办法调用微信支付 url连接 把dic传过去
# print('%s通过微信支付%s钱成功'%(self.name,money))
#
# WeChat('alex')
# 多态
# def add(int a,int b):
# return a+b
#
# print(add(1,'asuhjdhDgl'))
# class Payment:pass
# class WeChat(Payment):
# def __init__(self,name):
# self.name = name
# def pay(self,money):
# dic = {'username':self.name,'money':money}
# # 想办法调用微信支付 url连接 把dic传过去
# print('%s通过微信支付%s钱成功'%(self.name,money))
#
# class Apple(Payment):
# def __init__(self,name):
# self.name = name
# def pay(self,money):
# dic = {'name': self.name, 'number': money}
# # 想办法调用苹果支付 url连接 把dic传过去
# print('%s通过苹果支付%s钱成功' % (self.name, money))
#JAVA
# def pay(Payment a, int b):
# a.pay(b)
# obj = Apple('alex')
# pay(obj,400)
# obj = WeChat('alex')
# pay(obj,400)
# 一个类型表现出来的多种状态
# 支付 表现出的 微信支付和苹果支付这两种状态
# 在java情况下: 一个参数必须制定类型
# 所以如果想让两个类型的对象都可以传,那么必须让这两个类继承自一个父类,在制定类型的时候使用父类来指定
# 鸭子类型
# class list:
# def __init__(self,*args):
# self.l = [1,2,3]
# def __len__(self):
# n = 0
# for i in self.l:
# n+= 1
# return n
# l = [1,2,3]
# l.append(4)
# def len(obj):
# return obj.__len__()
# 所有实现了__len__方法的类,在调用len函数的时候,obj都说是鸭子类型
# 迭代器协议 __iter__ __next__ 是迭代器
# class lentype:pass
# class list(lentype):pass
# class dict(lentype):pass
# class set(lentype):pass
# class tuple(lentype):pass
# class str(lentype):pass
#
# def len(lentype obj):
# pass
# len(list)
# len(dict)
# len(set)
# len(tuple)
# len(str)
# class list:
# def __len__(self):pass
# class dict:
# def __len__(self): pass
# class set:
# def __len__(self): pass
# class tuple:
# def __len__(self): pass
# class str:
# def __len__(self): pass
# def len(鸭子类型看起来有没有实现一个__len__ obj):
# return obj.__len__()
多态抽象类总结
# 类的种类
# 新式类 : 继承object,存在在py2,py3(py3中都是新式类,py2里主动继承object的才是新式类)
# 经典类 : 只在py2中,不继承object默认是经典类
# 继承顺序
# 深度优先 : 经典类
# 广度优先 : 新式类
# 查看广度优先的顺序 : 类名.mro()
# 遵循的算法 :C3
# 抽象类
# 为什么要用抽象类 : 为了规范子类必须实现和父类的同名方法
# 抽象类用到的格式(至少会写一种,两种见到了都要认识)
# 不需要模块的
# class 父类:
# def 子类必须实现的方法名(self,参数们):
# raise NotImplementedError('提示信息')
# class 子类(父类):
# def 父类要求实现的方法(self,参数们):
# print('''code''')
# 需要模块的
# from abc import ABCMeta,abstractmethod
# class 父类(metaclass = ABCMeta):
# @abstractmethod
# def 子类必须实现的方法名(self,参数们):pass
# class 子类(父类):
# def 父类要求实现的方法(self,参数们):
# print('''code''')
# 归一化设计
# class A:
# def 同名功能(self):pass
# class B:
# def 同名功能(self):pass
#
# def 函数名(obj):
# obj.同名功能()
# 多态
# 什么是多态 : 一个类表现出的多种形态,实际上是通过继承来完成的
# 如果狗类继承动物类,猫类也继承动物类
# 那么我们就说猫的对象也是动物类型的
# 狗的对象也是动物类型的
# 在这一个例子里,动物这个类型表现出了猫和狗的形态
# java中的多态是什么样
# def eat(动物类型 猫的对象/狗的对象,str 食物):
# print('动物类型保证了猫和狗的对象都可以被传递进来')
# python中的多态是什么样 : 处处是多态
# 鸭子类型
# 子类继承父类,我们说子类是父类类型的(猫类继承动物,我们说猫也是动物)
# 在python中,一个类是不是属于某一个类型
# 不仅仅可以通过继承来完成
# 还可以是不继承,但是如果这个类满足了某些类型的特征条件
# 我们就说它长得像这个类型,那么他就是这个类型的鸭子类型
# 就记住两件事儿:
# 所有的类都必须继承object
# 如果见到了抽象类的写法,一定要知道要在子类中实现同名方法
10.super 封装 类的三个装饰器
super
# 在py3中怎么用?在py2(新式类/经典类)中怎么用?
在py3中不需要传参数,自动就帮我们寻找当前类的mro顺序的下一个类中的同名方法
在py2中的新式类中,需要我们主动传递参数super(子类的名字,子类的对象).函数名(), 这样才能够帮我们调用到这个子类的mro顺序的下一个类中的方法
在py2的经典类中,并不支持使用super来找下一个类
# 在单继承中执行父类的同名方法的时候怎么用?
在单继承的程序中,super就是找父类
# super方法和mro方法的关系是什么?
super是按照mro顺序来寻找当前类的下一个类
class A(object):
def func(self):
print('A')
class B(A):
def func(self):
super().func()
print('B')
class C(A):
def func(self):
super().func()
print('C')
class D(B,C):
def func(self):
super().func()
super(D,self).func()
print('D')
# D().func()
# D,B,C,A
# 在D类中找super的func,那么可以这样写 super().func()
# 也可以这样写 super(D,self).func() (并且在py2的新式类中必须这样写)
封装:就是把属性或者方法装起来
广义 :把属性和方法装起来,外面不能直接调用了,要通过类的名字来调用
狭义 :把属性和方法藏起来,外面不能调用,只能在内部偷偷调用
class User:
def __init__(self,name,passwd):
self.usr = name
self.__pwd = passwd # 私有的实例变量/私有的对象属性
alex = User('alex','sbsbsb')
print(alex.__pwd) # 报错
print(alex.pwd) # 报错
封装的语法:
#给一个名字前面加上了双下划线的时候,这个名字就变成了一个私有的
# 所有的私有的内容或者名字都不能在类的外部调用,只能在类的内部使用了
使用私有的三种情况
1.不想让你看也不想让你改
2.可以让你看 但不让你改
3.可以看也可以改 但是要求你按照我的规则改# class User:
# __ter = 'ID更多官方' #1.私有的静态变量
# def init(self,name,passwd):
# self.usr = name
# self.__pwd = passwd #2. 私有的实例变量/私有的对象属性
# def get_pwd(self): #3. 表示的是用户不能改只能看 私有 + 某个get方法实现的
# return self.__pwd
# def change_pwd(self):
pass
# 表示用户必须调用我们自定义的修改方式来进行变量的修改 私用 + change方法实现私有的特点:
可以在类的内部使用,不可以在类的外部使用,不能在类的子类中使用
原理:
# 加了双下划线的名字为啥不能从类的外部调用了?
# class User:
# __Country = 'China' # 私有的静态变量
# __Role = '法师' # 私有的静态变量
# def func(self):
# print(self.__Country) # 在类的内部使用的时候,自动的把当前这句话所在的类的名字拼在私有变量前完成变形
# print(User._User__Country)
# print(User._User__Role)
# __Country -->'_User__Country': 'China'
# __Role -->'_User__Role': '法师'
# User.__aaa = 'bbb' # 在类的外部根本不能定义私有的概念
类中变量级别,哪些是python支持,哪些是python不支持的
# public 公有的 类内类外都能用,父类子类都能用 python支持
# protect 保护的 类内能用,父类子类都能用,类外不能用 python不支持
# private 私有的 本类的类内部能用,其他地方都不能用 python支持
类中的三个装饰器
@property
property作用:1. 把一个方法伪装成一个属性,在调用这个方法的时候不需要加()就可以直接得到返回值
2.给伪装的属性方法赋值@函数名.setter装饰器
from math import pi
# class Circle:
# def __init__(self,r):
# self.r = r
#
# @property # 装饰的这个方法 不能有参数
# def area(self):
# return pi * self.r**2
#
# c1 = Circle(5)
# print(c1.r)
# print(c1.area)
property 的进阶 setter和delter
class Goods:
discount = 0.8
def __init__(self,name,origin_price):
self.name = name
self.__price = origin_price
@property
def price(self):
return self.__price * self.discount
@price.setter
def price(self,new_value):
if isinstance(new_value,int):
self.__price = new_value
@price.deleter
def price(self):
del self.__price
apple = Goods('apple',5)
print(apple.price) # 调用的是被@property装饰的price
apple.price = 'ashkaksk'# 调用的是被setter装饰的price
del apple.price # 并不能真的删除什么,只是调用对应的被@price.deleter装饰的方法而已
print(apple.price)
判断一个变量是不是可调用的,判断这个变量后面能不能加括号 : callable(名字)
11.反射.
使用条件:有些时候你明明知道一个变量的字符串数据类型的名字,你想调用它,但是调不到,就可以使用反射
反射中的几种情况:
# 1.反射对象的 实例变量/绑定方法
# 2.反射类的 静态变量/绑定方法/其他方法
# 3.模块中的 所有变量
# 被导入的模块
# 当前执行的py文件 - 脚本
getattr和hasattr
#字符串数据类型的变量名,采用getattr(对象,'变量名')获取变量的值
class A:
Role = '治疗'
def __init__(self):
self.name = 'alex'
self.age = 84
def func(self):
print('wahaha')
return 666
a = A()
print(getattr(a,'name')) # 反射对象的实例变量
print(getattr(a,'func')()) # 反射对象的绑定方法
print(getattr(A,'Role'))
import a # 引用模块中的任意的变量
print(getattr(a,'sww'),a.sww)
getattr(a,'sww')()
print(getattr(a,'lst'),a.lst)
print(getattr(a,'dic'),a.dic)
print(getattr(a,'we'),a.we)
import sys # 反射本模块中的名字
cat = '小a'
dog = '小b'
def pig():
print('小p')
print(getattr(sys.modules['__main__'],'cat'))
print(getattr(sys.modules['__main__'],'dog'))
getattr(sys.modules['__main__'],'pig')()
@classmethod : 被装饰的方法会成为一个类方法
把一个对象绑定的方法,修改成一个类方法
- 什么时候可以使用:1.定义了一个方法,默认传self,但是没有使用self
2.并且你在这个方法里用到了当前类名,或者你准备使用这个类的内存空间的名字的时候 好处:1.第一个在方法中仍然可以引用类中的静态变量
2.可以不用实例化对象,就直接用类名在外部调用这个方法
使用方法调用方法及例子
classmethod 被装饰的方法会成为一个类方法
class Goods:
__discount = 0.8
def __init__(self):
self.__price = 5
self.price = self.__price * self.__discount
@classmethod # 把一个对象绑定的方法 修改成一个 类方法
def change_discount(cls,new_discount):
cls.__discount = new_discount
# Goods.change_discount(0.6) # 类方法可以通过类名调用
# apple = Goods()
# print(apple.price)
# apple.change_discount(0.5) # 类方法可以通过对象名调用
# apple2 = Goods()
# print(apple2.price)
@staticmethod 被装饰的方法会成为一个静态方法
本身是一个普通的函数,被挪到类的内部执行,那么直接给这个函数添加@staticmethod就可以,这个函数的内部既不会用到self变量,也不会用到cls类
例子及调用方式
class User:
pass
@staticmethod
def login(a,b): # 本身是一个普通的函数,被挪到类的内部执行,那么直接给这个函数添加@staticmethod装饰器就可以了
print('登录的逻辑',a,b)
# 在函数的内部既不会用到self变量,也不会用到cls类
obj = User()
User.login(1,2)
obj.login(3,4)
能定义到类中的内容
- 静态变量 是个所有对象共享的变量 由对象\类调用,但是不能重新赋值
- 绑定方法 是个自带self参数的函数 由对象调用
- 类方法 是个自带cls参数的函数 由对象\类调用
- 静态方法 是个啥也不带的函数 由对象\类调用
- property属性 是个伪装成属性的方法 由对象调用 但是不加括号
12.内置的魔术方法
1.__new__
#什么时候执行?
实例化的时候
1.先创建一块对象的空间,有一个指针能指向类 --> __new__
2. 调用init --> __init__
#为什么要有,用来做什么?
创建一个对象需要的空间
#面试会考 单例模式
class Baby:
__instance = None
def __new__(cls, *args, **kwargs):
if cls.__instance is None:
cls.__instance = super().__new__(cls)
return cls.__instance
def __init__(self,cloth,pants):
self.cloth = cloth
self.pants = pants
b1 = Baby('红毛衣','绿皮裤')
print(b1.cloth)
b2 = Baby('白衬衫','黑豹纹')
print(b1.cloth)
print(b2.cloth)
2.__call__ 对象() 调用这个类中的__call__方法
# callable(对象)
# 对象() 能不能运行就是callable判断的事儿
class A:
def __call__(self, *args, **kwargs):
print('-------')
# obj = A()
# print(callable(obj))
# obj()
# A()()
# Flask框架的源码
3.__len__ : len(对象) 需要实现这个类中的__len__方法
例子及调用方法
class Cls:
def __init__(self,name):
self.name = name
self.students = []
def len(self):
return len(self.students)
def __len__(self):
return len(self.students)
py22 = Cls('py22')
py22.students.append('杜相玺')
py22.students.append('庄博')
py22.students.append('大壮')
print(py22.len())
print(len(py22))
4.__str__和__rerp__
在打印一个对象的时候 调用__str__方法
在%s拼接一个对象的时候 调用__str__方法
在str一个对象的时候 调用__str__方法
例子
class Course:
def __init__(self,name,price,period):
self.name = name
self.price = price
self.period = period
def __str__(self):
return self.name
python = Course('python',21800,'6 months')
linux = Course('linux',19800,'5 months')
mysql = Course('mysql',12800,'3 months')
go = Course('go',15800,'4 months')
print(go)
for index,c in enumerate(lst,1):
print(index,c)
num = int(input('>>>'))
course = lst[num-1]
print('恭喜您选择的课程为 %s 价格%s元'%(course.name,course.price))
class clas:
def __init__(self):
self.student = []
def append(self,name):
self.student.append(name)
def __str__(self):
return str(self.student)
py22 = clas()
py22.append('大壮')
print(py22)
print(str(py22))
print('我们py22班 %s'%py22)
print(py22)
py22.append('大壮')
print(py22)
__repr__方法
# 当我们打印一个对象 用%s进行字符串拼接 或者str(对象)总是调用这个对象的__str__方法
# 如果找不到__str__,就调用__repr__方法
# __repr__不仅是__str__的替代品,还有自己的功能
# 用%r进行字符串拼接 或者用repr(对象)的时候总是调用这个对象的__repr__方法