assert+条件,断言,用于强制用户服从,不服从就报错,可捕获,一般不捕获
assert 1==2
报错
一、两大编程思想
1.面向过程 事物比较简单,可以用线性思维去解决
2.面向对象 事物比较复杂,不可以用线性思维去解决
面向对象,便于从宏观上把握事物之间的联系,而具体到微观层面,依然使用面向过程处理。
二、类和对象创建
1.类:类是多个类似事物组成群体的统称。可帮助快速理解和判断事物的性质
2.类之下包含的相似的不同的个例 python中一切皆对象
# 默认继承object类
class bar:
# 类属性 类中方法外的属性 被该类所有方法共享
barda = 'barda'
# 初始化构造方法
def __init__(self,name,age):
self.name = name # 实例属性
self.__age = age # __表示私有属性
# 实例方法
def foo(self):
print(self.name,self.__age)
# 静态方法 不写self
@staticmethod
def method():
print('我是静态方法')
# 类方法 写cls
@classmethod
def classmeth(cls):
print('我是类方法')
# 对象创建 类的实例化
z=bar('zhao',21) # 创建时自动调用_init_方法
# print(id(z)) # 实例对象的内存地址 16进制 print(type(z)) # 类型 <class '__main__.bar'> print(z)
# print(id(bar)) # 类对象的内存地址 16进制 print(type(bar)) # 类型 <class 'type'> print(bar)
# 调用foo方法
z.foo()
bar.foo(z)
# 调用实例属性
print(z.name)
# 私有属性外部不可直接访问
# print(z.__age)
# 但是可以通过_类名__属性访问
print(z._bar__age)
# 类属性的调用
print(bar.barda)
print(z.barda)
# 类属性的修改
bar.barda='barda1'
print(z.barda)
# 类方法使用
bar.classmeth()
z.classmeth()
# 静态方法
bar.method()
z.method()
# 为z动态添加gender属性
z.gender = '女'
print(z.gender)
# 为z动态添加函数
def hello():
print('hello word')
z.hello = hello
z.hello()
# object类的方法
print(z.__dict__) # 将内容通过字典的形式返回 属性字典
# {'n': 'zhao', 'a': 21}
print(bar.__dict__) # 将对象中封装的所有内容通过字典的形式返回 方法字典
# {'__module__': '__main__', 'barda': 'barda1', '__init__': <function bar.__init__ at 0x0000021141E36EE8>, 'foo': <function bar.foo at 0x0000021141E3D558>, 'method': <staticmethod object at 0x0000021148E08A48>, 'classmeth': <classmethod object at 0x0000021148E08A88>, '__dict__': <attribute '__dict__' of 'bar' objects>, '__weakref__': <attribute '__weakref__' of 'bar' objects>, '__doc__': None}
class Foo:
stat = '999'
def __init__(self, name, age):
self.name = name
self.age = age
def show(self):
return "%s-%s" %(self.name,self.age)
def __int__(self):
return 123
# 重写object的str方法 返回对象描述
def __str__(self):
return self.name
obj = Foo('zz', 18)
# 取属性
print(obj.__dict__['name'])
print(getattr(obj,'name'))
print(getattr(Foo, 'stat'))
# 取方法
print(getattr(obj,'show')())
# str(obj)走__str__方法
u1 = str(obj) # zz
# int(obj)走__int__方法
u = int(obj) # 123
# 通过字符串的形式操作对象中的成员
print(hasattr(obj, 'show')) # 判断对象是否存在方法或属性
setattr(obj, 'k1', 'v1') # 添加字典的键k1和值v1
delattr(obj, 'name') # 删除属性
print(obj.__dict__) # {'age': 18, 'k1': 'v1'}
三、封装继承多态
封装:提高程序安全性,将数据和方法包装到类中
继承:复用性
多态:可扩展性和可维护性
类的继承 多继承
class Person(object): # 定义一个父类
def talk(self): # 父类中的方法
print("person is talking....")
class Chinese(Person): # 定义一个子类, 继承Person类
def walk(self): # 在子类中定义其自身的方法
print('Chinese is walking...')
c = Chinese( )
c.talk( ) # 调用继承的Person类的方法 person is talking....
c.walk( ) # 调用本身的方法 Chinese is walking...
class A(object):
pass
class B(object):
pass
class C(A,B):
pass
代码复用
class Tearch:
def __init__(self, name,age):
self.name = name
self.age = age
self.salary = 1000
class Course:
def __init__(self, name, cost, tearcher):
self.name = name
self.tearcher = tearcher
self.cost = cost
def class_up(self):
self.tearcher.salary += self.cost
t1 = Tearch('李杰' ,8)
t2 = Tearch('烧饼', 9)
c1 = Course('生理课', 1, t1)
print(c1.tearcher.salary) # 1000
c1.class_up()
print(c1.tearcher.salary) # 1001
class F1:
def __init__(self):
self.name = 123
class F2:
def __init__(self, a):
self.ff = a
class F3:
def __init__(self, b):
self.dd = b
f1 = F1() # [name=123]
print(f1.name)
f2 = F2(f1) # [ff=[name=123]]
print(f2.ff.name)
f3 = F3(f2) # [dd=[ff=[name=123]]]
print(f3.dd.ff.name)
子类对父类方法的重写
# 父类
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
self.weight = 'weight'
def talk(self):
print("person is talking....")
# 子类
class Chinese(Person):
def __init__(self, name, age, language):
# super().__init__(name, age)
super(Chinese, self).__init__(name, age)
# Person.__init__(self, name, age) # 继承父类的构造方法,也可以写成:super().__init__(name, age)
self.language = language # 定义类的本身属性
print(self.name, self.age, self.weight, self.language)
def talk(self): # 子类 方法重写
print('%s is speaking chinese' % self.name)
def walk(self):
print('%s is walking...' % self.name)
c = Chinese('zz', 15, 'Chinese') # zz 15 weight Chinese
c.talk( ) # zz is speaking chinese
四、特殊属性和方法
__dir__字典结构
__class__输出对象所属的类
__bases__父类的类别
__mro__类的层次结构方法
class Foo:
def f1(self):
return 123
def f2(self, v):
print(v)
def f3(self):
print('del')
per = property(fget=f1, fset=f2, fdel=f3)
obj = Foo()
# 取数据 走fget
ret = obj.per
print(ret) # 得到的值为f1函数执行的 返回123
# 设置数据 走fset
obj.per = 123456 # 设置值的为f2,输出传入的值
# 删除数据 走fdel
del obj.per # 删除时执行f3,打印del
class Foo:
def __init__(self, name,age):
self.name = name
self.age = age
def __getitem__(self, item):
# 如果item是基本类型:int,str,索引获取
# 若为slice对象的话,切片
if type(item) == slice:
print('调用者希望内部做切片处理')
else:
print(item.start)
print(item.stop)
print(item.step)
print('调用者希望内部做索引处理')
def __setitem__(self, key, value):
print(key,value)
def __delitem__(self, key):
print(key)
li = Foo('zz', 18) # 执行init方法
r=li[1:4:2] # 自动执行li对象的类中的__getitem__方法,[1:4:2]当作参数传递给item
li[1:3:1] = [11,22] # 自动执行li对象的类中的__setitem__方法,[1:3]和[11,22]传入
del li[1:3:1] # 自动执行li对象的类中的__delitem__方法
class Foo:
def __init__(self, name, age):
self.name = name
self.age = age
def __add__(self, other):
return Foo(obj1.name, other.age)
def __del__(self):
print('析构方法')
# 对象被销毁时自动执行,没有人用时可以销毁,但是什么时候销毁不知道
obj1 = Foo('zz', 19)
obj2 = Foo('xx', 66)
r = obj1 + obj2
# 两个对象相加时,自动执行第一个对象的 __add__方法,并且将第二个对象当作参数传递进入
print(r.name,r.age) # zz 66
metaclass
# 先__new__创建对象 再__init__赋值
class MyType(type):
def __init__(self,*args, **kwargs):
print(1)
def __call__(self, *args, **kwargs):
print(2)
r = self.__new__(1,2) # ③执行Foo的 __new__
self.__init__(self) # ④执行Foo的init函数
# 创建类时用mytype
class Foo(object,metaclass=MyType): # ①定义类时就执行MyType(type)的__init__()函数
def __init__(self):
print(4)
def __new__(self, *args, **kwargs):
print(3)
def func(self):
print('hello zz')
obj = Foo() # ②执行MyType(type)的__call__()
单例,永远使用同一份实例(对象)
class Foo:
__v = None
@classmethod
def get_instance(cls):
if cls.__v:
return cls.__v
else:
cls.__v = Foo( )
return cls.__v
# 以下2个对象一模一样,内存也一样
obj1 = Foo.get_instance( )
obj2 = Foo.get_instance( )
print(id(obj1),id(obj2))
类的深浅拷贝
变量的赋值操作,只是形成了两个变量,实际上还是指向同一个对象
浅拷贝:
一般都为浅拷贝,拷贝时对象包含的子对象的内容不拷贝,因此原对象与拷贝对象会引用同个子对象
深拷贝:
copy模块的deepcopy函数,递归拷贝对象包含的子对象