python 类
如果不会就不能说自己会编程
- 面向对象
- OOP编程是利用类和对象来创建各种模型来实现对真实世界的描述,基于面向对象的程序可以合人更容易理解代码逻辑。
class Dog: def bulk(self): print("Chenronghua:wangwangwang!!") d1=Dog();d2=Dog();d3=Dog() d1.bulk();d2.bulk();d3.bulk()
self 相当于把他自己传进去了=R1.NAME="HELLO" R1.MONEY=5000
class Dog: def __init__(self,name): self.name=name def bulk(self): print("%s:wangwangwang!!" %self.name) d1=Dog("chenronghua") d1.bulk()
对象也叫类的实例,
类变量class Role: n=1#类变量 print(Role.n)#结果是1
class Role: n=1#类变量 print(Role.n)#结果是1 a=Role();print(a.n)#对象可以直接访问类变量
class Role: n=1#类变量 a=Role();a.n=2 print(a.n)#对象里面有的话去对象里找,如果没有去类里面找
如果类里面没有的属性,你非要加上去,也是可以的。
del a.n print(a.n)#可以删除属性
实例改不了类变量,如果你想改,其实并不是在改,而是在给实例赋新的属性。但是实例变量也是可以通过ROLE.n来改类变量
类变量的化用就是共用的属性,可以省内存。- 析构函数:在实例释放的时候,销毁的时候做的工作,比如关闭数据库连接,
-
class Role: n=1#类变量 def __del__(self):#没有参数 print("i'm die")
del R1#释放实例
-
- 私有属性
class Role: n=1#类变量 def __init__(self,name): self.__name=name def __del__(self): print("i'm die") a=Role("xiaoxu") print(a.__name)#这样是访问 不了的,想要访问就要再定义一个方法
class Role: n=1#类变量 def __init__(self,name): self.__name=name def getname(self): print(self.__name)#专门做一个方法来访问私有属性 def __del__(self): print("i'm die") a=Role("xiaoxu") print(a.__name)#这样是访问 不了的,想要访问就要再定义一个方法 私有方法也是这样定义的 “__"加上两个下划线
- 析构函数:在实例释放的时候,销毁的时候做的工作,比如关闭数据库连接,
- 封装
- 继承
-
class peple: pass class men(peple): pass
重构父类的方法
class peple: def sleep(self): print("peple is sleeping") class men(peple): def sleep(self): print("men is sleeping") xu=men();xu.sleep() #men is sleeping
class peple: def sleep(self): print("peple is sleeping") class men(peple): def sleep(self): peple.sleep(self) print("men is sleeping") xu=men();xu.sleep() # peple is sleeping # men is sleeping
上面给父方法加了一个新功能
那如果子类里面想要再传一个参数过去怎么办?class peple: def __init__(self,name,age): self.name=name self.age=age def sleep(self): print("peple is sleeping") class men(peple): def __init__(self,name,age,money): peple.__init__(self,name,age) self.money=money def sleep(self): peple.sleep(self) print("men is sleeping") xu=men("xiaoxu",29,1000);print(xu.money) #1000
还有一种写法是,这种方法的好处就是跟上下文刘关系弱了,要不然只要改了父类的名字,所有的都要改,而且多继承的时候怎么办所以有这个方法。
class peple:#新式类的写法是class peple(object) def __init__(self,name,age): self.name=name self.age=age def sleep(self): print("peple is sleeping") class men(peple): def __init__(self,name,age,money): #peple.__init__(self,name,age) super(men,self).__init__(name,age) self.money=money def sleep(self): peple.sleep(self) print("men is sleeping") xu=men("xiaoxu",29,1000);print(xu.money) #1000
新式类和经典类的不同在于继承的方式不同(经典类没有SUPER)
- 类的继承顺序是,广度优先(CLASS d(b,c)) 找构造的顺序是先找自己,再找B 还找不到 就找C 还找不到就找A
-
- 多态
- 一种接口,多种实现
- 静态方法 @staticmethod
class peple(object): def __init__(self,name): self.name=name def chi(self,food): print("%s is eating%s"%(self.name,food)) xiaoxu=peple("xiaoxu") xiaoxu.chi("面条")
此时没有问题但是如果给CHI函数加上静态的属性,就有点类似CHI这个函数跟PEPLE这个类没有关系了,有点相当于我给你提供了一个功能,但是这个功能我是放在类里面的,要不然我不能给你一个函数让你 用,就比如说,百度给了我一个接口让可以使用人脸识别,他给了我一个类,这个类里面有一个‘功能’就是看这个人的脸大还是脸小,这跟识别出这是谁没有关系,这个功能我自己写不出来,他(百度)给我提供了一个这个的功能,这个功能可以是跟类没关系的,我是直接可以用的。
class peple(object): def __init__(self,name): self.name=name @staticmethod def chi(self,food): print("%s is eating%s"%(self.name,food)) xiaoxu=peple("xiaoxu") peple.chi(xiaoxu,"红薯") #xiaoxu is eating红薯,这个方法是封装在PEPLE类里面的,把PEPLE换成XIAOXU也是一样的结果。因为他跟类和实例 好像都没有什么太大关系,只是封装在这个类里面一起给你了。
类方法@classmethod修饰,特性就是类方法里只能访问类变量,不能访问实例变量,看起来似乎是比一个正常的方法还有局限,正常的方法 什么都 可以用, 类方法却不能,没什么用至今。
@property 属性方法 把一个方法 变成 一个静态属性, 不用加 括号 就可以调用。 也就不能传参数了。
类的特殊方法
1 __doc__class A: ''' 你好我是类的说明 ''' def __init__(self): self.name="xiaoxu" b=A() print(b.__doc__)
2 __module__ 看看是哪个模块来的
from a.b import C f=C() f.hello() print(f.__module__) #a.b
3 __class__ 看看是哪个类
from a.b import C f=C() f.hello() print(f.__class__) #<class 'a.b.C'>
4 __call__ 可以继续传参数给实例
class A: def __call__(self, *args, **kwargs): print(args,kwargs) a1=A() a1(123,321,1234567,name=1,password=2) #(123, 321, 1234567) {'name': 1, 'password': 2}
5 __dict__查看成员
class A: def __init__(self,name): self.name=name def hello(self): pass a1=A("xiaoxu") print(A.__dict__) print(a1.__dict__) # {'__module__': '__main__', '__init__': <function A.__init__ at 0x005AC588>, 'hello': <function A.hello at 0x005AC5D0>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None} # {'name': 'xiaoxu'}
6 __str__ 打印对象是显示的信息
class A: def __init__(self,name): self.name=name def hello(self): pass a1=A("name") print(a1) #<__main__.A object at 0x00961FB0>
class A: def __init__(self,name): self.name=name def hello(self): pass def __str__(self): return "i'm %s"%self.name a1=A("name") print(a1) #i'm name
7 __getitem__ ....... set item 就是把类做成一个字典
class Food(object): def __getitem__(self, key): print('__getitem__',key) def __setitem__(self, key, value): print('__setitem__',key,value) def __delitem__(self, key): print('__delitem',key) obj=Food() obj['name']='xiaoxu' # __setitem__ name xiaoxu
class Food(object): def __init__(self): self.data={} def __getitem__(self, key): print('__getitem__',key) def __setitem__(self, key, value): print('__setitem__',key,value) self.data[key]=value def __delitem__(self, key): print('__delitem',key) obj=Food() obj['name']='xiaoxu' print(obj.data) # __setitem__ name xiaoxu. # {'name': 'xiaoxu'}
__new__ 先于 __init__执行 用来创建实例的 一般不用写 可以加功能 但不要覆盖
其中CLS代表的是FOO类这个对象,像SELF代表实例一样
class Foo(object): def __new__(cls, *args, **kwargs): print("我是第一") def __init__(self,name): print("我是第二") f1=Foo() # 我是第一
class Foo(object): def __new__(cls, *args, **kwargs): print("我是第一") return object.__new__(cls) def __init__(self): print("我是第二") f1=Foo() # 我是第一 # 我是第二
return object.__new__(cls)相当于继承了父类的NEW方法
- OOP编程是利用类和对象来创建各种模型来实现对真实世界的描述,基于面向对象的程序可以合人更容易理解代码逻辑。
- 反射
# -*- encoding=utf-8 -*- class Dog(object): def __init__(self,name): self.name=name def eat(self): print("%s is eating"%self.name) d=Dog("小黑") choice=input("请输入方法").strip() #现在我想用户输入一个EAT 就调用这个实例吃的方法 if choice=='eat': d.eat() #但是我现在有好多好多方法 总不能写好多好多CHOICE进去所以我有一个想法,看看用户输入的词是不是方法 print(hasattr(d,choice)) #v如果有这个方法就会显示TRUE 没有就是FALSE 但是这并不是我想要的我想输入就执行 getattr(d,choice) #这时就得到了这个方法的内存地址 ,但是他还是不会执行, 它既然是一个方法 的内存地址那我直接执行就可以了啊 getattr(d,choice)() # 请输入方法eat # 小黑 is eating # True # 小黑 is eating
print("%s is yelling..."%self.name) class Dog(object): def __init__(self,name): self.name=name def eat(self): print("%s is eating"%self.name) d=Dog("小黑") choice=input("请输入方法").strip() #现在我想用户输入一个EAT 就调用这个实例吃的方法 if choice=='eat': d.eat() #但是我现在有好多好多方法 总不能写好多好多CHOICE进去所以我有一个想法,看看用户输入的词是不是方法 print(hasattr(d,choice)) #v如果有这个方法就会显示TRUE 没有就是FALSE 但是这并不是我想要的我想输入就执行 #这时就得到了这个方法的内存地址 ,但是他还是不会执行, 它既然是一个方法 的内存地址那我直接执行就可以了啊 if hasattr(d,choice): getattr(d,choice)() #func=getattr(d,choice) #func() else: setattr(d,choice,bulk) d.talk(d) # 请输入方法talk # False # 小黑 is yelling...
动态的加一个方法,因为TALK是输入进去的 不能这样直接调用 因为 写死了 可以变通一下代码利用GETATTR
# -*- encoding=utf-8 -*- def bulk(self): print("%s is yelling"%self.name) class Dog(object): def __init__(self,name): self.name=name def eat(self): print("%s is eating.."%self.name) d=Dog("xiaoxu") choice=input("fangfa").strip() if hasattr(d,choice): getattr(d,choice)()#method else: setattr(d,choice,bulk) getattr(d,choice)(d)
这样就动态家里一个方法,可是属性怎么办大概可以这样
def bulk(self): print("%s is yelling"%self.name) class Dog(object): def __init__(self,name): self.name=name def eat(self): print("%s is eating.."%self.name) d=Dog("xiaoxu") choice=input("fangfa").strip() if hasattr(d,choice): getattr(d,choice)()#method else: setattr(d,choice,22) print(getattr(d,choice))
- 异常处理
try: pass except (KeyError,IndexError) as e: print(e) #如果多个错误就这样处理
try: pass except Exception as e: print(e) 处理所有的错误
自定义异常