面向对象编程
class Person: # 类名
def __init__(self,name,sex,job,hp,weapon,ad):
# 必须叫__init__这个名字,不能改变的,所有的在一个具体的人物出现之后拥有的属性
self.name = name
self.sex = sex
self.job = job
self.level = 0
self.hp = hp
self.weapon = weapon
self.ad = ad
# # 类名() 会自动调用类中的__init__方法
# 类名() 会自动调用类中的__init__方法
alex = Person('alex','不详','搓澡工',260,'搓澡巾',1) # alex 就是对象 alex = Person()的过程 是通过类获取一个对象的过程 - 实例化
print(alex,alex.__dict__)
wusir = Person('wusir','male','法师',500,'打狗棍',1000)
print(wusir,wusir.__dict__)
print(alex.name) # print(alex.__dict__['name']) 属性的查看
alex.name = 'alexsb' # 属性的修改
print(alex.name)
alex.money = 1000000 # 属性的增加
print(alex.money)
print(alex.__dict__)
del alex.money # 属性的删除
print(alex.__dict__)
-
类名() 会自动调用类中的__init__方法
-
通过对象名.__dict__就可以查看这个对象的属性和值
类和对象之间的关系?
-
类 是一个大范围 是一个模子 它约束了事物有哪些属性 但是不能约束具体的值
-
对象 是一个具体的内容 是模子的产物 它遵循了类的约束 同时给属性赋上具体的值
了解实例化对象所经历的步骤
-
# 实例化所经历的步骤 # 1.的类名() 之后第一个事儿 :开辟一块儿内存空间 # 2.调用 __init__ 把空间的内存地址作为self参数传递到函数内部 # 3.所有的这一个对象需要使用的属性都需要和self关联起来 # 4.执行完init中的逻辑之后,self变量会自动的被返回到调用处(发生实例化的地方)
初识方法
class Person: # 类名
def __init__(self,name,sex,job,hp,weapon,ad):
self.name = name # 对象的属性/实例变量
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))
class Dog():
def __init__(self,name,blood,aggr,kind):
self.dog_name = name
self.hp = blood
self.ad = aggr
self.kind = kind
def 舔(self,person):
# 狗舔了人,人调血,人掉的血量,应该是狗的攻击力
if person.hp >= self.ad:
person.hp -= self.ad
else:
person.hp = 0
print(self.__dict__)
print(person.__dict__)
print('%s舔了%s,%s掉了%s点血,%s当前血量%s'%(self.dog_name,person.name,person.name,self.ad,person.name,person.hp))
alex = Person('alex','不详','搓澡工',260,'搓澡巾',1) # 对象\实例 = 类名() --> 实例化的过程
print('alex : ',alex)
小白 = Dog('小白',5000,249,'柴犬')
# alex.搓(小白)
小白.舔(alex)
小白.舔(alex)
练习
定义一个圆形类,半径是这个圆形的属性,实例化一个半径为5的圆形,一个半径为10的圆形
完成方法
计算圆形面积
计算圆形周长
math import pi
class Circle:
'''定义一个圆形类'''
def __init__(self,radius):
self.radius = radius
def area(self):
return pi*self.radius**2
def perimeter(self):
return 2*pi*self.radius
circle = Circle(5) # 实例化
area1 = circle.area() # 计算面积
print(area1)
per1 = circle.perimeter() # 计算圆周长
print(per1)
定义一个用户类,用户名和密码是这个类的属性,实例化两个用户,分别有不同的用户名和密码
登陆成功之后才创建用户对象
设计一个方法 修改密码
import os
def login(name,passwd,filepath = 'userinfo'):
with open(filepath,encoding='utf-8') as f:
for line in f:
user,pwd = line.strip().split('|')
if user == name and passwd == pwd:
return True
else:
return False
class User:
def __init__(self,username,password):
self.user = username
self.pwd = password
def change_pwd(self):
oldpwd = input('输入原密码 :')
newpwd = input('输入新密码 :')
flag = False
with open('userinfo',encoding='utf-8') as f1,open('userinfo1',mode='w',encoding='utf-8') as f2:
for line in f1:
username,password = line.strip().split('|')
if username == self.user and password == oldpwd:
line = '%s|%s\n'%(username,newpwd)
flag = True
f2.write(line)
os.remove('userinfo')
os.rename('userinfo1','userinfo')
return flag
name = input('user : ')
passwd = input('pwd : ')
ret = login(name,passwd)
if ret:
print('登录成功')
obj = User(name,passwd)
res = obj.change_pwd()
if res:
print('修改成功')
类的成员和命名空间
class A:
Country = '中国' # 静态变量/静态属性 存储在类的命名空间里的
def __init__(self,name,age): # 绑定方法 存储在类的命名空间里的
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)
print(a.name) # alex
print(a.Country) # 中国
print(A.Country) # 中国
a.func1() # == A.func1(a)
class A:
Country = '中国' # 静态变量/静态属性 存储在类的命名空间里的
def __init__(self,name,age,country): # 绑定方法 存储在类的命名空间里的
self.name = name
self.age = age
self.Country = country
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) # 中国
-
1.类中的变量是静态变量
2.对象中的变量只属于对象本身,每个对象有属于自己的空间来存储对象的变量
3.当使用对象名去调用某一个属性的时候会优先在自己的空间中寻找,找不到再去对应的类中寻找
4.如果自己没有就引用类的,如果类也没有就报错
5.对于类来说,类中的变量所有的对象都是可以读取的,并且读取的是同一份变量 -
类中的静态变量的用处
-
如果一个变量 是所有的对象共享的值,那么这个变量应该被定义成静态变量 所有和 静态变量相关的增删改查 都应该使用类名来处理 而不应该使用 对象名直接修改 静态变量
-
-
将对象变成了一个属性
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) # 6 months
print(linux57.course.price) # 19800
linux.price = 21800 # 修改属性
print(linux57.course.price) # 21800
print(linux58.course.price) # 21800
继承
- 解决代码的重复
# 继承语法:
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() # 小白 is eating
小白.climb_tree() # 小白 is climbing
小黑 = Dog('小黑')
小黑.eat() # 小黑 is eating
- 当子类和父类中的方法重名的时候,我们只使用子类的方法,不会调用父类的方法
class Animal:
def __init__(self,name):
self.name = name
def eat(self):
print('%s is eating'%self.name)
class Cat(Animal):
def eat(self):
print('%s吃猫粮'%self.name)
小白 = Cat('小白')
小白.eat() # 小白吃猫粮
- 子类想要调用父类的方法的同时,还想执行自己的同名方法
- 比如猫和狗在调用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))
class Cat(Animal):
def eat(self):
self.blood +=100
Animal.eat(self)
def climb_tree(self):
print('%s is climbing'%self.name)
class Dog(Animal):
def eat(self):
self.waise +=100
Animal.eat(self)
def house_keep(self):
print('%s house keeping'%self.name)
小白 = Cat('小白','猫粮')
小黑 = Dog('小黑','狗粮')
小白.eat()
小黑.eat()
print(小白.__dict__)
print(小黑.__dict__)
>>>小白 is eating 猫粮
>>>小黑 is eating 狗粮
>>>{'name': '小白', 'food': '猫粮', 'blood': 200, 'waise': 100}
>>>{'name': '小黑', 'food': '狗粮', 'blood': 100, 'waise': 200}
- 父类和子类方法的选择
- 子类的对象,如果取去用方法永远优先调用自己的
- 如果自己有 用自己
- 如果没有 用父类的
- 如果自己有,还想用父类的:直接在子类方法中调用父类的方法:父类名.方法名(self)
- 思考一:下面代码的输出
class Foo:
def __init__(self):
self.func() # 在每一个self调用func的时候,我们不看这句话是在哪里执行,只看self是谁
def func(self):
print('in foo')
class Son(Foo):
def func(self):
print('in son')
Son() # in son
- 思考二:如何给猫定制个性的属性
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)
# 猫:eye_color眼睛的蓝色
class Cat(Animal):
def __init__(self,name,food,eye_color):
# Animal.__init__(self,name,food) # 调用了父类的初始化,去完成一些通用属性的初始化
super().__init__(name,food)
self.eye_color = eye_color # 派生属性
小白 = Cat('小白','猫粮','蓝色')
print(小白.__dict__)
- 单继承
- 调子类:子类自己有的时候
调父类的:子类自己没有的时候
调子类和父类的:子类父类都有,在子类中调用父类的
- 调子类:子类自己有的时候
# class D:
# def func(self):
# print('in D')
# class C(D):
# pass
# class A(C):
# pass
# class B(A):
# pass
# b = B()
# b.func() # in D
# class D:
# def func(self):
# print('in D')
# class C(D):
# pass
# class A(C):
# def func(self):
# print('in A')
# class B(A):
# pass
# b = B()
# b.func() # in A
- 绑定方法和普通的函数
from types import FunctionType,MethodType
FunctionType : 函数
MethodType : 方法
isinstance type
a = 1
b = 'abc'
print(isinstance(a,int)) # True
print(isinstance(a,float)) # False
print(isinstance(b,str))
a = 1
b = 'abc'
print(type(a) is int)
print(type(b) is str)
class Cat:
pass
小白 = Cat()
print(type(小白) is Cat) # <class '__main__.Cat'> # True
print(isinstance(小白,Cat))
class Animal:
pass
class Cat(Animal):
pass
小白 = Cat()
print(type(小白) is Cat) # True
print(type(小白) is Animal) # False
print(isinstance(小白,Cat)) # True
print(isinstance(小白,Animal)) # True
绑定方法和普通的函数
from types import FunctionType,MethodType
FunctionType : 函数
MethodType : 方法
class A:
def func(self):
print('in func')
print(A.func) # 函数 <function A.func at 0x000002477EA363A0>
a = A()
print(a.func) # 方法 <bound method A.func of <__main__.A object at 0x000002477E9901C0>>
print(isinstance(a.func,FunctionType)) # False
print(isinstance(a.func,MethodType)) # True
print(isinstance(A.func,FunctionType)) # True
print(isinstance(A.func,MethodType)) # False
一:我们定义的类的属性到底存到哪里了?有两种方式查看
dir(类名):查出的是一个名字列表
类名.__dict__:查出的是一个字典,key为属性名,value为属性值
二:特殊的类属性
类名.__name__# 类的名字(字符串)
类名.__doc__# 类的文档字符串----查看注释
类名.__base__# 类的第一个父类
类名.__bases__# 类所有父类构成的元组
类名.__dict__# 类的字典属性
类名.__module__# 类定义所在的模块
类名.__class__# 实例对应的类(仅新式类中(python3))
class A:
role = '法师'
def func1(self):pass
def func2(self):pass
class B:
pass
class C(B,A):
pass
print(A.__base__) # <class 'object'>
print(C.__base__) # <class '__main__.B'>
print(C.__bases__) # (<class '__main__.B'>, <class '__main__.A'>)
print(A.__dict__) # {'__module__': '__main__', 'role': '法师', 'func1': <function A.func1 at 0x0000024F54EB6430>, 'func2': <function A.func2 at 0x0000024F54EB64C0>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
print(A.__name__) # A
print(A.__class__) # <class 'type'>
print(B.__class__) # <class 'type'>
print(C.__class__) # <class 'type'>
print(C.__module__) # __main__
# __doc__:查看注释
def func():
'''
这个函数主要是用来卖萌
:return:
'''
pass
print(func.__doc__)
>>>
这个函数主要是用来卖萌
:return:
类的继承顺序
-
只要继承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 class C(A): pass class D(B,C): pass # 查看在新式类中的继承顺序 print(D.mro()) # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
- mro练习
class A: pass class B(A): pass class C(A): pass class D(B): pass class E(C): pass class F(D,E): pass print(F.mro()) # [<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
- 广度优先
-
# 广度优先遵循C3算法,要会用mro,会查看顺序 # 经典类没有mro,但新式类有
super方法:
class A(object):
def func(self):
print('A')
class B(A):
def func(self):
super().func()
print('B')
class C(B):
def func(self):
super().func()
print('C')
C().func() # A--B--C
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()
print('D')
D().func()
print(D.mro()) # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
- 在子类中,新建的重名的函数属性,在编辑函数内功能的时候,有可能需要重用父类中重名的那个函数功能
class Animal:
'''
人和狗都是动物,所以创造一个Animal基类
'''
def __init__(self, name, aggressivity, life_value):
self.name = name # 人和狗都有自己的昵称;
self.aggressivity = aggressivity # 人和狗都有自己的攻击力;
self.life_value = life_value # 人和狗都有自己的生命值;
def eat(self):
print('%s is eating'%self.name)
class Dog(Animal):
'''
狗类,继承Animal类
'''
def __init__(self,name,breed,aggressivity,life_value):
super().__init__(name, aggressivity, life_value) #执行父类Animal的init方法
self.breed = breed #派生出了新的属性
def bite(self, people):
'''
派生出了新的技能:狗有咬人的技能
:param people:
'''
people.life_value -= self.aggressivity
def eat(self):
# Animal.eat(self)
#super().eat()
print('from Dog')
class Person(Animal):
'''
人类,继承Animal
'''
def __init__(self,name,aggressivity, life_value,money):
#Animal.__init__(self, name, aggressivity, life_value)
#super(Person, self).__init__(name, aggressivity, life_value)
super().__init__(name,aggressivity, life_value) #执行父类的init方法
self.money = money #派生出了新的属性
def attack(self, dog):
'''
派生出了新的技能:人有攻击的技能
:param dog:
'''
dog.life_value -= self.aggressivity
def eat(self):
#super().eat()
Animal.eat(self)
print('from Person')
egg = Person('egon',10,1000,600)
ha2 = Dog('二愣子','哈士奇',10,1000)
print(egg.name)
print(ha2.name)
egg.eat()
C3算法:
# 单继承
A(O) = [AO] ------A继承O
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的规则 :如果一个类出现在从左到右所有顺序的最左侧,并且没有在其他位置出现,那么先提出来作为继承顺序中的一个
- 或 一个类出现在从左到右顺序的最左侧,并没有在其他顺序中出现,那么先提出来作为继承顺序中的一个
- 如果从左到右第一个顺序中的第一个类出现在后面且不是第一个,那么不能提取,顺序向后继续找其他顺序中符合上述条件的类
- merge的规则 :如果一个类出现在从左到右所有顺序的最左侧,并且没有在其他位置出现,那么先提出来作为继承顺序中的一个
-
- 经典类 - 深度优先 新式类 - 广度优先
广度优先遵循C3算法,要会用mro,会查看顺序
经典类没有mro,但新式类有
抽象类
- 是一个开发的规范 约束他的所有子类必须实现一些和他同名的方法
super
- super遵循mro算法
- 只在新式类中能使用(不区分py2 py3)
- 在py2中的新式类中,需要我们主动传递参数super(子类的名字,子类的对象).函数名()
class A(object):
def func(self):
print('A')
class B(A):
def func(self):
super().func()
print('B')
class C(B):
def func(self):
super().func()
print('C')
C().func() # A--B--C
# 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()
# print('D')
# D().func()
# print(D.mro()) # [<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
封装
-
把属性或者方法装起来
- 广义 :把属性和方法装起来,外面不能直接调用了,要通过类的名字来调用
- 狭义 :把属性和方法藏起来,外面不能调用,只能在内部偷偷调用
-
给一个名字前面加上了双下划线的时候,这个名字就变成了一个私有的
- 所有的私有的内容或者名字都不能在类的外部调 用,只能在类的内部使用了
- 类的外部不能定义私有的概念
-
所有的私有化都是为了让用户不在外部调用类中的某个名字
-
如果完成私有化 那么这个类的封装度就更高了 封装度越高各种属性和方法的安全性也越高 但是代码越复杂
class User:
def __init__(self,name,passwd):
self.usr = name
self.__pwd = passwd # 私有的实例变量
alex = User('alex','sbsbsb')
print(alex.__pwd) # 报错
print(alex.pwd) # 报错
查看私有属性
class User:
def __init__(self,name,passwd):
self.usr = name
self.__pwd = passwd # 私有的实例变量/私有的对象属性
def get_pwd(self): # 表示的是用户不能改只能看 私有 + 某个get方法实现的
return self.__pwd
alex = User('alex','sbsbsb')
print(alex.get_pwd()) # sbsbsb
修改私有属性
class User:
def __init__(self,name,passwd):
self.usr = name
self.__pwd = passwd # 私有的实例变量/私有的对象属性
def get_pwd(self): # 表示的是用户不能改只能看 私有 + 某个get方法实现的
return self.__pwd
def change_pwd(self): # 表示用户必须调用我们自定义的修改方式来进行变量的修改 私用 + change方法实现
pass
alex = User('alex','sbsbsb')
print(alex.get_pwd())
class User:
__Country = 'China' # 私有的静态变量
def func(self):
print(User.__Country) # 在类的内部可以调用
# print(User.Country) # 报错 在类的外部不能调用
# print(User.__Country)# 报错 在类的外部不能调用
User().func()
import hashlib
class User:
def __init__(self,name,passwd):
self.usr = name
self.__pwd = passwd # 私有的实例变量
def __get_md5(self): # 私有的绑定方法
md5 = hashlib.md5(self.usr.encode('utf-8')) # 加盐处理
md5.update(self.__pwd.encode('utf-8')) # 使用update方法进行加密
return md5.hexdigest()
# 获取私有方法
def getpwd(self):
return self.__get_md5()
alex = User('alex','sbsbsb')
print(alex.getpwd())
加了双下划线的名字为啥不能从类的外部调用了?
class User:
__Country = 'China' # 私有的静态变量
__Role = '法师' # 私有的静态变量
def func(self):
print(self.__Country) # 在类的内部使用的时候,自动的把当前这句话所在的类的名字拼在私有变量前完成变形
print(User.__dict__)
print(User._User__Country) # 不建议使用
print(User._User__Role) # 不建议使用
# __Country -->'_User__Country': 'China'
# __Role -->'_User__Role': '法师'
User.__aaa = 'bbb' # 在类的外部根本不能定义私有的概念
print(User.__dict__)
私有的内容能不能被子类使用呢? 不能
class Foo(object):
def __init__(self):
self.__func() #只会与自己所在的类为准,即调用_Foo__func
def __func(self): # 变形为 _Foo__func
print('in Foo')
class Son(Foo):
def __func(self): # 变形为 _Son__func
print('in Son')
Son() # in Foo
class Foo(object):
def __func(self):
print('in Foo')
class Son(Foo):
def __init__(self):
self.__func()
Son() # AttributeError: 'Son' object has no attribute '_Son__func'
在其他语言中的数据的级别都有哪些?在python中有哪些
# public 公有的 类内类外都能用,父类子类都能用 python支持
# protect 保护的 类内能用,父类子类都能用,类外不能用 python不支持
# private 私有的 本类的类内部能用,其他地方都不能用 python支持
@property装饰器
- 把一个方法伪装成一个属性,在调用这个方法的时候 不需要加() 就可以直接得到返回值
- 变量的属性和方法?
- 属性 :圆形的半径\圆形的面积
- 方法 :登录 注册
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)
- 装饰的这个方法 不能有参数
import time
class Person:
def __init__(self,name,birth):
self.name = name
self.birth = birth
@property
def age(self): # 装饰的这个方法 不能有参数
return time.localtime().tm_year - self.birth
太白 = Person('太白',1998)
print(太白.age) # 22
- 私有的属性合作的
class User:
def __init__(self,usr,pwd):
self.usr = usr
self.__pwd = pwd
@property
def pwd(self):
return self.__pwd
alex = User('alex','sbsbsb')
print(alex.pwd)
# 商业大酬宾
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
apple = Goods('apple',5)
print(apple.price)
进阶
- 给伪装的数学的方法赋值 @函数名.setter 装饰器
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
apple = Goods('apple',5)
print(apple.price) # 调用的是被@property装饰的price # 4.0 获取商品价格
apple.price = 10 # 调用的是被setter装饰的price 修改商品原价
print(apple.price) # 8.0
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)
apple.price = 10
del apple.price # 并不能真的删除什么,只是调用对应的被@price.deleter装饰的方法而已
print(apple.price)
反射
-
通过字符串的形式操作对象相关的属性
-
1.反射对象的 实例变量/绑定方法
-
class Person: def __init__(self,name,age): self.name = name self.age = age def qqxing(self): print('qqxing') alex = Person('alex',83) wusir = Person('wusir',74) # 对象名.属性名 ==> getattr(对象名,'属性名') ret = getattr(alex,'name') print(ret) ret = getattr(wusir,'name') print(ret) ret = getattr(wusir,'qqxing') print(ret) # <bound method Person.qqxing of <__main__.Person object at 0x000001C33615E790>> print(wusir.qqxing) # <bound method Person.qqxing of <__main__.Person object at 0x000001CD724AE790>> ret()
-
2.反射类的 静态变量/其他方法
-
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')) # 反射静态变量
-
-
3.模块中的 所有变量
-
# import a # 引用模块中的任意的变量 # print(getattr(a,'sww'),a.sww) # <function sww at 0x0000023D5E73A940> <function sww at 0x0000023D5E73A940> # # getattr(a,'sww')() # 爽歪歪 # print(getattr(a,'lst'),a.lst) # [1, 2, 3, 4, 5] [1, 2, 3, 4, 5] # print(getattr(a,'dic'),a.dic) # {'k': 'v'} {'k': 'v'} # print(getattr(a,'we'),a.we) # <a.Wechat object at 0x0000023D5E7309D0> <a.Wechat object at 0x0000023D5E7309D0>
-
被导入的模块
-
a.py文件: class Wechat:pass class Alipay:pass def sww(): print('爽歪歪') lst = [1,2,3,4,5] dic = {'k':'v'} we = Wechat() py文件 import a print(a.Wechat) # <class 'a.Wechat'> print(a.Alipay) # <class 'a.Alipay'> # 对象名.属性名 ==> getattr(对象名,'属性名') # a.Alipay ==> getattr(a,'Alipay') print(getattr(a, 'Alipay')) print(getattr(a, 'Wechat'))
import a import sys print(sys.modules['a']) # <module 'a' from 'E:\\老男孩22期\\面向对象\\day26\\a.py'> print(a) # <module 'a' from 'E:\\老男孩22期\\面向对象\\day26\\a.py'> print(sys.modules['a'].Alipay) # <class 'a.Alipay'> print(a.Alipay) # <class 'a.Alipay'> print(getattr(a,'Alipay')) # <class 'a.Alipay'> print(getattr(sys.modules['a'],'Alipay')) # <class 'a.Alipay'>
-
-
当前执行的py文件 - 脚本(反射本文件中的内容)
-
wahaha = 'hahaha' print(getattr(sys.modules['__main__'],'wahaha'))
import sys # 反射本模块中的名字 cat = '小a' dog = '小b' def pig(): print('小p') print(getattr(sys.modules['__main__'],'cat')) # 小a print(getattr(sys.modules['__main__'],'dog')) # 小b getattr(sys.modules['__main__'],'pig')() # 小p
-
反射的例子
-
-
class Payment:
pass
class Alipay(Payment):
def __init__(self,name):
self.name = name
def pay(self,money):
dic = {'uname':self.name,'price':money}
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}
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}
print('%s通过苹果支付%s钱成功' % (self.name, money))
class QQpay:
def __init__(self,name):
self.name = name
def pay(self,money):
print('%s通过qq支付%s钱成功' % (self.name, money))
import sys
def pay(name,price,kind):
class_name = getattr(sys.modules['__main__'],kind)
obj = class_name(name)
obj.pay(price)
# 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')
pay('alex',400,'QQpay')
- 与反射有关的内置函数 callable
class A:
Role = '治疗'
def __init__(self):
self.name = 'alex'
self.age = 84
def func(self):
print('wahaha')
return 666
a = A()
# print(getattr(a,'sex')) # AttributeError: 'A' object has no attribute 'sex'
# print(hasattr(a,'sex')) # False
# print(hasattr(a,'age')) # True
# print(hasattr(a,'func')) # True
# 检测是否含有某属性
if hasattr(a,'func'):
# 检查一个对象是否是可调用的
if callable(getattr(a,'func')):
getattr(a,'func')() # wahaha
getattr
def getattr(object, name, default=None): # known special case of getattr
"""
getattr(object, name[, default]) -> value
Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
When a default argument is given, it is returned when the attribute doesn't
exist; without it, an exception is raised in that case.
"""
pass
@classmethod
-
被装饰的方法会成为一个类方法
-
定义了一个方法,默认传self,但是这个self没有被使用
classmethod
class Goods:
__discount = 0.8
def __init__(self):
self.__price = 5
self.price = self.__price*self.__discount
def change_discount(self,new_discount):
# 不能写self.__discount ---->在self的命名空间创建
Goods.__discount = new_discount
# 定义了一个方法,默认传self,但是这个self没有被使用
apple = Goods()
# 调用实例变量
print(apple.price) # 4.0
# 修改折扣
apple.change_discount(0.6)
apple2 = Goods()
print(apple2.price) # 3.0
- 把一个对象绑定的方法,修改成一个类方法
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指向当前所在类的名字,而不是self指向对象的名字
# print(cls,Goods)
cls.__discount = new_discount
#
#
Goods.change_discount(0.6) # 可以通过类名调用
apple = Goods()
print(apple.price) # 3.0
apple.change_discount(0.5) # 可以通过对象名调用
apple2 = Goods()
print(apple2.price) # 2.5>
apple2 = Goods()
print(apple2.price) # 3.0
- 在自己的类里,做了对自己类的实例化
import time
class Date:
def __init__(self,year,month,day):
self.year = year
self.month = month
self.day = day
@classmethod
def today(cls):
struct_t = time.localtime()
# 在自己的类里,做了对自己类的实例化
date = cls(struct_t.tm_year,struct_t.tm_mon,struct_t.tm_mday)
return date
date的对象 = Date.today()
print(date的对象.year)
print(date的对象.month)
print(date的对象.day)
- 何时使用classmethod?
- 1.定义了一个方法,默认传self,但是这个self没有被使用
- 2.并且在这个方法里用到了当前的类名,或者你准备使用这个类的内存空间的名字的时候
- classmethod:
- 1.在方法中可以引用类中的静态变量
- 2.可以不用实例化对象,就直接用类名在外部调用这个方法
- 可以通过类名调用
- 可以通过对象名调用
@staticmethod
- 被装饰的方法会成为一个静态方法
- 什么时候用?
- 帮助我们把一个普通的函数挪动到类中来直接使用,制造静态方法用的
class Uers():
pass
@staticmethod
def login(a,b): # 本身是一个普通的函数,被移动到类的内部执行,直接给这个函数添加staticmethod装饰器
print('登录的逻辑',a,b)
# 在函数的内部既不会用到self(对象)变量,也不会用到cls类
obj = User()
# 通过类名.方法名 调用
Uers.login(1,2)
- 能定义到类中的内容
-
静态变量 是个所有的对象共享的变量 由对象\类调用 不能重新赋值
-
绑定方法 是个自带self参数的函数 由对象调用
-
类方法 是个自带cls参数的函数 由对象\类调用
-
静态方法 是个啥都不带的普通函数 由对象\类调用
-
property属性 是个伪装成属性的方法 由对象调用,但不加()
-
class A:
country = '中国' # 静态变量
def func(self): # 绑定方法
print(self.__dict__)
@classmethod # 类方法
def clas_func(cls):
print(cls)
@staticmethod # 静态方法
def stat_func():
print('这是一个普通函数')
@property # 将一个方法伪装成属性
def name(self):
return 'wahaha'
魔术方法
new
- 实例化的时候
- 先创建一块空间,有一个指针能指向类—>new
- 然后调用init
class A:
def __new__(cls, *args, **kwargs): # 构造方法
print('执行new')
return super().__new__(cls)
def __init__(self):
print('执行init')
A()
执行我了
执行init
class A:
def __new__(cls, *args, **kwargs): # 构造方法
o = super().__new__(cls)
print('执行new',o)
return o
def __init__(self):
print('执行init',self)
A()
设计模式 – 单例模式
- 一个类 从头到尾 只会创建一次 self的空间
class Baby:
def __init__(self,cloth,pants):
self.name = cloth
self.age = pants
# 开辟了两块内存空间
b1 = Baby('红毛衣','绿皮库')
b2 = Baby('白衬衫','黑豹文')
print(b1) # <__main__.Baby object at 0x0000027BD7914580>
print(b2) # <__main__.Baby object at 0x0000027BD792EDC0>
# 只开辟一块内存空间
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) # 白衬衫
call
- 对象() 调用这个类中的__call__方法
# callable(对象)
# 对象() 能不能运行就是callable判断的事儿
class A:
def __call__(self, *args, **kwargs):
print('-------')
obj = A()
print(callable(obj)) # True
obj() # 对象() 调用__call__
A()() # A()--对象 A()()--对象()
# Flask框架的源码
len
- len(对象) 需要实现这个类中的__len__方法
class Cls:
def __init__(self,name):
self.name = name
self.students= []
py22 = Cls('py22')
py22.students.append('杜相玺')
py22.students.append('董宇航')
py22.students.append('大壮')
# 查看班里有几个同学
print(len(py22.students)) # 3
class Cls:
def __init__(self,name):
self.name = name
self.students= []
def __len__(self):
return len(self.students)
py22 = Cls('py22')
py22.students.append('杜相玺')
py22.students.append('董宇航')
py22.students.append('大壮')
# 查看班里有几个同学
print(len(py22)) # len(对象) 需要实现这个类中的__len__方法
class Pow():
def __init__(self,n):
self.n = n
def __pow2__(self):
return self.n**2
def pow2(obj):
return obj.__pow2__()
obj = Pow(10)
print(pow2(obj))
str__和__repr
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')
# 在打印一个对象的时候 调用__str__方法
print(go) # go
lst = [python,linux,mysql,go]
for index,c in enumerate(lst,1): # enumerate内置函数
# 用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标
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) # ['大壮']-----字符串数据类型
# 在str一个对象的时候 调用__str__方法
print(str(py22)) # ['大壮']
# 在%s拼接一个对象的时候 调用__str__方法
print('我们py22班 %s'%py22) # 我们py22班 ['大壮']
print(py22) # ['大壮']
py22.append('大壮')
print(py22) # ['大壮', '大壮']
- 在打印一个对象的时候 调用__str__方法
- 在%s拼接一个对象的时候 调用__str__方法
- 在str一个对象的时候 调用__str__方法
class clas:
def __init__(self):
self.student = []
def append(self,name):
self.student.append(name)
def __repr__(self): # 只能返回一个字符串数据类型
return str(self.student)
py22 = clas()
py22.append('大壮')
print(py22) # ['大壮']-----字符串数据类型
print(str(py22)) # ['大壮']
print('我们py22班 %s'%py22) # 我们py22班 ['大壮']
print(py22) # ['大壮']
py22.append('大壮')
print(py22) # ['大壮', '大壮']
-
当我们打印一个对象 或用%s进行字符串拼接 或者str(对象)总是调用这个对象的__str__方法
-
如果找不到__str__,就调用__repr__方法
-
__repr__不仅是__str__的替代品,还有自己的功能
-
用**%r进行字符串拼接** 或者用repr(对象)的时候总是调用这个对象的__repr__方法
class clas:
def __init__(self):
self.student = []
def append(self,name):
self.student.append(name)
def __repr__(self):
return str(self.student)
def __str__(self):
return 'aaa'
py22 = clas()
py22.append('大壮')
print(py22) # aaa
print(str(py22)) # aaa
print('我们py22班 %s'%py22) # 我们py22班 aaa
print('我们py22班 %r'%py22) # 我们py22班 ['大壮']
print(repr(py22)) # ['大壮']