---恢复内容开始---
# import os # os.rename("复习.py","02复习.py") # 面向对象: #理解:写代码时什么时候用面向对象 。处理比较复杂的角色之间关系的时候(代码量多,功能多的时候)# 可以解决角色之间的功能,去掉重复代码 # 代码清晰度更高,无论开发者还是使用者都能理解各种角色的方法和属性 # python里面一切皆对象 #基础数据类型都是对象。都有属于它明确的方法和属性 # 类型和类的关系 # 类型和类是一个东西 # type(obj) obj是一个对象,那么他的type就是他的类型 # 创建一个类 # 类名()实例化 # __new__()创造一个对象的空间,一些简单的初始化 # 创建一个对象 # class 类名 语法级别的python解释器读到这句话时 # type是所有类的元类,object是所有类的基类 # 类也是被创建出来的,type创建类 # class A(metaclass = type) # type(cls) = type # 那么type就是这个类的元类 # type(obj)的结果就是这个对象所属的类 # # type(cls)的结果就是创建这个类的元类,大多数情况下都是type ,除非指定元类 class A(metaclass = 指定元类名) # class A: # pass # a = A() print(type(a)) # <class '__main__.A'> # print(type(A))# <class 'type'>
类
面试题
class Lei: ROLE = "china" print(ROLE) # 这里会直接打印
class Lei: ROLE = "qqq" print(ROLE) # 这里会直接打印 print(Person.ROLE) # NameError: name 'Person' is not defined # 原因。这里执行这个类时先从上到下先执行一便,执行完后把Person指向这个空间 def func(self):pass
# 类是什么时候被加载的以及类是什么时候生效的
# 对象
# 类创造对象的过程就是实例化过程 构造new,初始化init
#可以通过指针找到类空间和的内容
# 对象本身内部也存储了一些只属于对象的属性
# 组合
#什么有什么的关系
# 一个类本身的对象作为另一个对象的属性
继承
单继承和多继承
# 继承 # 单继承和多继承 # 单继承 # 子类的对象调用某个方法 # 子类有: 调用子类的 # 子类有但调用父类的: # super #super().方法名(除开self所有的参数) # 父类名 # 父类名.方法名(self....) # 在任何类中调用的方法,都要自行辨别这个self到底是谁的对象 # class Foo: # def __init__(self): # self.func() # # def func(self): # print("Foo.func") # # class Son(Foo): # def func(self): # print("Son.func") # s = Son() # Son.func # 多继承 # 新式类 广度优先 - C3算法 # mro方法查看继承顺序 # py3默认都是新式类,py2默认都是经典类 # 经典类:深度优先 # 不继承object # 没有mro class A: 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 = D() # d.func() # A # C # B # D # b = B() # # b.func() # # A # # B
# 根据mro c3算法
子类和父类
# 子类和父类 #什么是什么的关系 # 经典类和新式类 # 抽象类和接口类 # 不能被实例化 #规范子类当中必须实现某个方法 # 有原生的实现抽象类的方法,但没有原生实现接口类的方法 # java中 只支持单继承。于是就有了interface接口的概念,接口支持多继承。j # python中不严格区分接口类和抽象类
多态
# 多态 # 一种类型的多种形态 多个子类去继承父类,每一个子类都是父类的一种形态 class Animal:pass class Tiger(Animal):pass class Frog(Animal):pass # 处处都是多态 #鸭子类型 # 规范全凭自觉
封装
# 封装 私有的 # 广义的封装 把方法和属性都封装在一个类型,定义一个规范来描述一类事物 # 狭义的封装 私有化 只能在类的内部访问 # __静态变量 私有方法 私有的对象属性 私有的类方法 私有的静态方法 # 在内存中存储的 _类名__名字 # 为什么在类中的内部可以使用__访问:在类的内部访问,程序知道自己在哪个类里面 # 在子类中可以访问父类的私有变量嘛.不行 # 私有,不能在类的外部,也不能被继承
property
# property 帮助你将类中的方法伪装成属性 # 调用方法的时候不需要主动加括号 # 让程序的逻辑性更加合理 # @方法名.setter 装饰器.修改被property装饰的属性的时候就会调用被这个装饰器装饰的方法.除了self 之外还有一个参数被修改的值 # @方法名.deleter 装饰器,当要删除被property装饰的属性的时候会调用这个被这个装饰器装饰的方法 class A: @property def name(self): # 这个方法本身就是一个属性,这个变量会随着这个类/对象的一些基础变量的变化而变化 return "abc" @name.deleter # def name(self): # del A.name def name(self): print("dudud") a = A() print(a.name) del a.name # 执行这句话的时候会执行 @name.deleter def name(self): del A.name 这段代码.如果修改为其他操作,他仍然会执行.
# classmethod
#classmethod 类方法的装饰器,内置函数 # 使用类名调用,默认传类名为第一个参数 # 不用对象命名空间中的内容,而用到了类命名空间中的变量(静态属性),或者类方法和静态方法.. class Goods: __discount = 0.8 def __init__(self,price): self.__price = price @property def price(self): return self.__price * self.__discount # def change_diccount(self,num): # Goods.__discount = num # 因为不需要使用任何实例上的操做,所以如果只要类名调用的更好 @classmethod def change_discount(cls,num): cls.__discount = num # 商场的程序 apple = Goods(10) banana = Goods(15) print(apple.price) # apple.change_diccount(1.0) Goods.change_discount(1.0) print(apple.price) print(banana.price)
staticmethod
# staticmethod 静态方法的装饰器 内置函数 # 如果一个类里面的方法,既不需要用到self中的资源,也不用到cls的资源 # 相当于一个普通函数 # 但是由于一些原因,把这个方法放入类中,这时候就得把这个方法变成静态方法
列表操作时 insert(位置,参数) 和pop(n) 会浪费大量时间 pop()和append()可以使用
反射
# 反射 从某个指定的命名空间中,用字符数据类型的变量名来获取变量的值 # 类名反射 静态属性 类方法 静态方法 # 对象反射 对象属性 方法 # 模块反射 模块中的方法 # 自己模块中 # import sys # myfile = sys.modules['__main__'] # getattr(myfile,'变量名') # hasattr /getattr / setattr / delattr # 参数 # (明明空间,"变量名") # setattr(命名空间,"变量名","新的值") # 变量名 # 只能拿到字符串的版本 # 从文件里拿 # 交互拿 :input/网络传输
进阶
# 进阶 # 内置方法 /魔术方法/双下方法 # __名字__ 不是被直接掉用的 # 内置函数/面向对象中特殊方法/python提供的语法糖 # __str__,str(obj)必须在对象中实现了obj方法,并且这个方法返回的数据类型必须是str类型 __call__,(用类写转世器的时候必须使用) # __new__,(在实例化的过程中,最先执行的方法,用来创建方法) __len__,要求这个方法的返回值必须返回int类型,len(obj) 要求obj必须实现了__len__方法__init__(实例化的工程中在new执行后自动执行) # x = 5 # y = 6 # print(x.__add__(y)) class Mytype: def __init__(self,a): self.a = a def __add__(self, other): # 这里的other也是一个对象 return self.a.count('*') + other.a.count('*') obj1 = Mytype("afa***DGFD**") obj2 = Mytype("dasFASF**HEFsfe**BVF") print(obj1.__add__(obj2)) print(obj2 + obj1) # 语法糖 __add__ 对应+
# __repr__
# a = "123"
# print(a)
# print(repr(a))
class A:
def __init__(self,name):
self.name = name
def __repr__(self):
return self.name
def __str__(self):
return "{}**".format(self.name)
class B(A):
def __init__(self,name):
self.name = name
def __repr__(self):
return "B"
a = A("abc")
print(a) # 在没有__str__的情况下,str print %s # 都根据repr返回, 如果有则返回__str__ str print %s 都会根据str返回
print(str(a)) # 调用类里面的__str__
print(repr(a)) # 调用而是__repr__
print("%s | %r" %(a,a))
# __repr__对应的是repr(obj) 和%r ,在没有__str__的情况下会 对应 str print %s
b = B("acnd")
print(b)
print(str(b)) # 在本类中没有找到__str__, 于是就找父类的str,值到找遍除了object外的所有父类都没有找到__str_,那么就找本类的__repr__
c = "cccc"
print("----%s-----" % repr(c))
print("----%r------" % str(c))