添加对象或类的属性哪里(类__init__
方法中、类方法中、类外)都可以添加。
class A:
def __init__(self,name):
self.name = name
def func(self,sex):
self.sex = sex
# 类外面可以:
obj = A('barry')
obj.age = 18
print(obj.__dict__) # {'name': 'barry', 'age': 18}
# 类内部也可以:
obj = A('barry') # __init__方法可以。
obj.func('男') # func 方法也可以。
对象查找属性的顺序:先从对象空间找 ------> 类空间找 ------> 父类空间找 ------->…
类名查找属性的顺序:先从本类空间找 -------> 父类空间找--------> …
上面的顺序都是单向不可逆,类名不可能找到对象的属性。
将一个类的对象或者类名传到另一个类的方法使用. 这种关系比较弱。
关联关系, 其实就是 我需要你. 你也属于我
组合:将一个类的对象封装到另一个类的对象的属性中,就叫组合。
继承分为单继承和多继承
这里需要补充一下python中类的种类(继承需要): 在python2x版本中存在两种类.: ⼀个叫经典类. 在python2.2之前. ⼀直使⽤的是经典类. 经典类在基类的根如果什么都不写. ⼀个叫新式类. 在python2.2之后出现了新式类. 新式类的特点是基类的根是object类。 python3x版本中只有一种类: python3中使⽤的都是新式类. 如果基类谁都不继承. 那这个类会默认继承 object类。
__init__
方法,类中没有,从父类找,父类没有,从object
类中找。父类.func(对象,其他参数)
super().func(参数)
一个类继承多个类
c3
算法
MRO
class A:
def f1(self):
print('in A f1')
def f2(self):
print('in A f2')
class Foo(A):
def f1(self):
super().f2()
print('in A Foo')
obj = Foo()
obj.f1()
class A:
def f1(self):
print('in A')
class Foo(A):
def f1(self):
super().f1()
print('in Foo')
class Bar(A):
def f1(self):
print('in Bar')
class Info(Foo,Bar):
def f1(self):
super().f1()
print('in Info f1')
obj = Info()
obj.f1()
'''
in Bar
in Foo
in Info f1
'''
print(Info.mro()) # [<class '__main__.Info'>, <class '__main__.Foo'>, <class '__main__.Bar'>, <class '__main__.A'>, <class 'object'>]
class A:
def f1(self):
print('in A')
class Foo(A):
def f1(self):
super().f1()
print('in Foo')
class Bar(A):
def f1(self):
print('in Bar')
class Info(Foo,Bar):
def f1(self):
super(Foo,self).f1()
print('in Info f1')
obj = Info()
obj.f1()
将属性写到__init__
中
同样名称的方法在不同的子类中会有不同的行为。
同⼀个对象, 多种形态. 这个在python中其实是很不容易说明⽩的. 因为我们⼀直在⽤. 只是没有具体的说. 比如. 我们创建⼀个变量a = 10 , 我们知道此时a是整数类型. 但是我们可以通过程序让a = “太白”, 这时, a⼜变成了字符串类型. 这是我们都知道的. 但是, 我要告诉你的是. 这个就是多态性. 同⼀个变量a可以是多种形态。
class Payment:
"""
此类什么都不做,就是制定一个标准,谁继承我,必须定义我里面的方法。
"""
def pay(self,money):
raise Exception("你没有实现pay方法")
class QQpay(Payment):
def pay(self,money):
print('使用qq支付%s元' % money)
class Alipay(Payment):
def pay(self,money):
print('使用阿里支付%s元' % money)
class Wechatpay(Payment):
def fuqian(self,money):
print('使用微信支付%s元' % money)
def pay(obj,money):
obj.pay(money)
a = Alipay()
b = QQpay()
c = Wechatpay()
pay(a,100)
pay(b,200)
pay(c,300)
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):
# 抽象类 接口类 规范和约束 metaclass指定的是一个元类
@abstractmethod
def pay(self):pass # 抽象方法
class Alipay(Payment):
def pay(self,money):
print('使用支付宝支付了%s元'%money)
class QQpay(Payment):
def pay(self,money):
print('使用qq支付了%s元'%money)
class Wechatpay(Payment):
# def pay(self,money):
# print('使用微信支付了%s元'%money)
def recharge(self):pass
def pay(a,money):
a.pay(money)
a = Alipay()
a.pay(100)
pay(a,100) # 归一化设计:不管是哪一个类的对象,都调用同一个函数去完成相似的功能
q = QQpay()
q.pay(100)
pay(q,100)
w = Wechatpay()
pay(w,100) # 到用的时候才会报错
抽象类和接口类做的事情 :建立规范,只要子类继承了我写的这个抽象类,实例化对象时就会报错。
对于每一个类的成员而言都有两种形式:
类 | 类 | 类内部 | 派生类 |
---|---|---|---|
公有类的静态属性 | 可以访问 | 可以访问 | 可以访问 |
公有方法 | 可以访问 | 可以访问 | 可以访问 |
私有类的静态属性 | 不可以访问 | 可以访问 | 不可以访问 |
私有方法 | 不可以访问 | 可以访问 | 不可以访问 |
对象属性 | 对象 | 类内部 | 派生类 |
---|---|---|---|
公有对象属性 | 可以访问 | 可以访问 | 可以访问 |
私有对象属性 | 不可以访问 | 可以访问 | 不可以访问 |
对于这些私有成员来说,他们只能在类的内部使用,不能再类的外部以及派生类中使用.
使用装饰器@classmethod。第一个参数必须是当前类对象,该参数名一般约定为“cls”,通过它来传递类的属性和方法(不能传实例的属性和方法);
调用:实例对象和类对象都可以调用。
class Student:
__num = 0
def __init__(self,name,age):
self.name = name
self.age= age
Student.addNum() # 写在__new__方法中比较合适,但是现在还没有学,暂且放到这里
@classmethod
def addNum(cls):
cls.__num += 1
@classmethod
def getNum(cls):
return cls.__num
a = Student('太白金星', 18)
b = Student('barry', 18)
print(Student.getNum())
定义:使用装饰器@staticmethod。参数随意,没有“self”和“cls”参数,但是方法体中不能使用类或实例的任何属性和方法;
调用:实例对象和类对象都可以调用。
静态方法是类中的函数,不需要实例化。可以理解为,静态方法是个独立的、单纯的函数,仅仅托管于某个类的名称空间中,便于使用和维护。
import time
class TimeTest(object):
def __init__(self, hour, minute, second):
self.hour = hour
self.minute = minute
self.second = second
@staticmethod
def showTime():
return time.strftime("%H:%M:%S", time.localtime())
print(TimeTest.showTime())
t = TimeTest(2, 10, 10)
nowTime = t.showTime()
print(nowTime)
property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值
将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则
class Foo:
@property
def AAA(self):
print('get的时候运行我啊')
@AAA.setter
def AAA(self,value):
print('set的时候运行我啊')
@AAA.deleter
def AAA(self):
print('delete的时候运行我啊')
#只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter
f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA
#或者:
class Foo:
def get_AAA(self):
print('get的时候运行我啊')
def set_AAA(self,value):
print('set的时候运行我啊')
def delete_AAA(self):
print('delete的时候运行我啊')
AAA=property(get_AAA,set_AAA,delete_AAA) #内置property三个参数与get,set,delete一一对应
f1=Foo()
f1.AAA
f1.AAA='aaa'
del f1.AAA
python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
Python实现自省的函数hasattr
、getattr
、setattr
、delattr
class Foo:
f = '类的静态变量'
def __init__(self,name,age):
self.name=name
self.age=age
def say_hi(self):
print('hi,%s'%self.name)
obj=Foo('egon',73)
#检测是否含有某属性
print(hasattr(obj,'name'))
print(hasattr(obj,'say_hi'))
#获取属性
n=getattr(obj,'name')
print(n)
func=getattr(obj,'say_hi')
func()
print(getattr(obj,'aaaaaaaa','不存在啊')) #报错
#设置属性
setattr(obj,'sb',True)
setattr(obj,'show_name',lambda self:self.name+'sb')
print(obj.__dict__)
print(obj.show_name(obj))
#删除属性
delattr(obj,'age')
delattr(obj,'show_name')
delattr(obj,'show_name111')#不存在,则报错
print(obj.__dict__)
与对象基本相同
更优雅的写代码?
class User:
def login(self):
print('欢迎来到登录页面')
def register(self):
print('欢迎来到注册页面')
def save(self):
print('欢迎来到存储页面')
user = User()
while 1:
choose = input('>>>').strip()
if hasattr(user,choose): #如果user存在choose这个属性
func = getattr(user,choose)#取这个属性并赋值给func变量
func()#执行
else:
print('输入错误。。。。')
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x IOError 输入/输出异常;基本上是无法打开文件 ImportError 无法引入模块或包;基本上是路径问题或名称错误 IndentationError 语法错误(的子类) ;代码没有正确对齐 IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5] KeyError 试图访问字典里不存在的键 KeyboardInterrupt Ctrl+C被按下 NameError 使用一个还未被赋予对象的变量 SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了) TypeError 传入对象类型与要求的不符合 UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量, 导致你以为正在访问它 ValueError 传入一个调用者不期望的值,即使值的类型是正确的
基本语法:
try:
被检测的代码块
except 异常类型:
try中一旦检测到异常,就执行这个位置的逻辑
多分支+万能异常
dic = {
1: login,
2: register,
3: dariy,
4: article,
5: comment,
}
print('''
欢迎访问博客园系统:
1,登录
2,注册
3,访问日记页面
4,访问文章页面
5,访问评论页面
''')
try:
choice = int(input('请输入:'))
dic[choice]()
# if choice.isdigit():
# if
#
# else:
# print('请输入数字...')
except ValueError:
print('请输入数字....')
except KeyError:
print('您输入的选项超出范围...')
except Exception as e:
print(e)
# 伪代码
try:
print('扣第一个人钱')
...
print('给第二个人加钱')
except ValueError:
print('必须输入数字。。。')
else:
print('转账成功')
try:
dic = {'name': '太白金星'}
print(dic[1])
except KeyError:
print('出现了keyError错误....')
finally:
print('正常执行')
try:
dic = {'name': '太白金星'}
print(dic[1])
except NameError:
print('出现了NameError错误....')
finally:
print('异常发生之前,先执行我')
f = open('file',encoding='utf-8')
try:
'''各种操作'''
print(f.read())
'''但是发生错误了, 此时没关闭文件句柄,所以'''
finally:
f.close()
def func():
try:
return 1
finally:
print('finally')
func()
while 1:
try:
break
finally:
print('finally')
raise TypeError('类型错误')
# assert 条件
assert 1 == 1
assert 1 == 2
# 应用:
assert 条件
代码
代码
.......
# assert 条件
assert 1 == 1
assert 1 == 2
# 应用:
assert 条件
代码
代码
.......