面向对象程序设计
面向过程编程:就是分析问题的解决步骤,按部就班的编写代码解决问题
函数式编程:就是把代码封装到函数中,然后在使用时调用封装好的函数
面向对象编程:把一类事物所共有的属性和行为提取出来,从而增加程序的扩展性
一、什么是面向对象程序设计?
面向对象程序设计(Object-oriented programming,OOP)是一种程序设计范型,也是一种程序开发方法。将一类事物的动作和特征整合到一起就是面向对象程序设计
二、什么是类?什么是对象?
类:一类事物共有的特征和行为
对象:某个具有类中属性和行为的个体
三、类的声明
1 class Foo(object):#新式类, 2 pass 3 4 class Foo():#经典类 5 pass 6 """ 7 在Python 2及以前的版本中,由任意内置类型派生出的类(只要一个内置类型位于类树的某个位置),都属于“新式类”,都会获得所有“新式类”的特性;反之,即不由任意内置类型派生出的类,则称之为“经典类”。 8 9 “新式类”和“经典类”的区分在Python 3之后就已经不存在,在Python 3.x之后的版本,因为所有的类都派生自内置类型object(即使没有显示的继承object类型),即所有的类都是“新式类”。 10 """
四、类的属性
数据属性:类中的变量
函数属性:类中定义的方法
五、类内置方法
①__dict__属性字典
对象的属性字典只有数据属性,因为对象之间是共享类的函数属性的
类的属性字典,包括类的数据属性和函数属
1 class Foo(object): 2 x = 10 3 def __init__(self,a): 4 self.a = a 5 def show_a(self): 6 print(self.a) 7 8 f1 = Foo(2) 9 print(f1.__dict__) 10 print(Foo.__dict__) 11 12 13 {'a': 2} 14 {'__module__': '__main__', 'x': 10, '__init__': <function Foo.__init__ at 0x000002A051CC4AE8>, 'show_a': <function Foo.show_a at 0x000002A051CC4B70>, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None}
②__name__类名
print(Foo.__name__) Foo
③__bases__基类
1 class Foo(): 2 pass 3 4 class Boo(Foo): 5 pass 6 7 print(Boo.__bases__)#返回元组形式 8 9 (<class '__main__.Foo'>,)
④__init__() 初始化方法
1 class Foo(): 2 def __init__(self): 3 print("创建类对象时执行初始化方法") 4 5 f1 = Foo()#实例化类,也就是创建类对象 6 7 创建类对象时执行初始化方法
六、对象访问类中的变量的顺序
实例化的对象访问类中的变量时,先访问初始化方法init中的属性,如若没有就会访问init方法外的类里的,再没有就会报错
1 class Foo(object): 2 a = 10 3 def __init__(self,a): 4 self.a = a 5 6 f1 = Foo(2) 7 print(f1.a) 8 9 10 2
1 class Foo(object): 2 x = 10 3 def __init__(self,a): 4 self.a = a 5 def show_a(self): 6 print(self.a) 7 8 f1 = Foo(2) 9 print(f1.x) 10 11 10
1 class Foo(object): 2 x = 10 3 def __init__(self,a): 4 self.a = a 5 def show_a(self): 6 print(self.a) 7 8 f1 = Foo(2) 9 print(f1.q) 10 11 AttributeError: 'Foo' object has no attribute 'q'
七、实例化对象只会保存init方法中的变量,只含有数据属性,需要调用类的函数属性
八、类调用类方法需要指定self参数,参数任意
1 class Foo(): 2 def show(self): 3 print("show") 4 5 6 #Foo.show(1) 7 #Foo.show(“sunqi”) 8 #Foo.show([1,2,3]) 9 10 11 show
九、实例增加方法时需要需要传self参数
1 class Foo(): 2 def __init__(self,a): 3 self.a = a 4 def show(self): 5 print("show") 6 7 f1 = Foo("111") 8 def hello(self): 9 print("hello") 10 11 f1.fun = hello 12 f1.fun("sss")#必须指定self参数(可以是任意对象) 13 print(f1.__dict__) 14 15 hello
十、property 方法
property方法会将类中的定义的方法变成变量,直接返回结果,隐藏逻辑
加括号调用时会报错
1 class Foo(): 2 def __init__(self,a,b): 3 self.a = a 4 self.b = b 5 # @property 6 def cal(self): 7 return self.a + self.b 8 f1 = Foo(1,2) 9 print(f1.cal) 10 11 12 <bound method Foo.cal of <__main__.Foo object at 0x0000019C642E2128>>
1 class Foo(): 2 def __init__(self,a,b): 3 self.a = a 4 self.b = b 5 @property 6 def cal(self): 7 return self.a + self.b 8 f1 = Foo(1,2) 9 print(f1.cal) 10 11 12 3
十一、类方法classmethod
当我们想要用类调用类中定义的方法且不希望指定self对象是,我们就可以 采用classmethod声明一个类方法
1 @classmethod 2 def tell_info(cls,[name,x]):可用更多参数 3 pass
1 class Foo(): 2 def func1(self): 3 print("类中的方法") 4 5 @classmethod 6 def func3(cls,x):#类方法cls参数python自动指定类名,其他参数必须传值 7 print("cls--name",cls.__name__) 8 print("-->",x) 9 10 11 f1 = Foo() 12 f1.func3(1) 13 print("*"*10) 14 Foo.func3(1) 15 print(f1.func3) 16 print(Foo.func3) 17 18 19 cls--name Foo 20 --> 1 21 ********** 22 cls--name Foo 23 --> 1 24 <bound method Foo.func3 of <class '__main__.Foo'>> 25 <bound method Foo.func3 of <class '__main__.Foo'>>
十二、静态方法staticmethod
类中的没有修饰符,没有self,没有cls的普通方法实例是不能调用的,因为会默认给该方法穿第一个self参数,会报错
1 class Foo(): 2 def func(): 3 print("func1") 4 f1 = Foo() 5 f1.func() 6 7 默认传参self 8 TypeError: func() takes 0 positional arguments but 1 was given
那么我们如何用实例调用这种方法。这时候就需要用staticmethod声明一个普通方法
1 class Foo(): 2 @staticmethod 3 def func(): 4 print("func1") 5 f1 = Foo() 6 f1.func() 7 8 func1
十三、getattr,hasattr,setattr,delattr反射
1 hasattr(b1,"name") 检测object中有没有一个name字符串对应的属性 2 getattr(b1,"name"),default 得到属性的值,设置default时 即使没有参数不会报错 3 setattr(b1,"name"," ")设置对象属性值,也可以添加函数属性 可以是匿名函数 4 delattr(b1,"name")删除对象的属性
1 class B(): 2 c = 1 3 def __init__(self,a,b): 4 self.a = a 5 self.b = b 6 def func(self): 7 print(self.a) 8 print(self.b) 9 10 def fun(): 11 print("fun") 12 13 b1 = B(1,2) 14 # print(hasattr(b1,"func"))#判断对象是否有name属性 15 # print(getattr(b1,"func","not exist"))#存在就会返回该对象 16 # print(getattr(b1,"sun","not exist"))#不存在返回设置的默认值 17 # print(getattr(b1,"a"))#1 18 # print(setattr(b1,"func1",lambda x:x+1)) 19 # print(setattr(b1,"func1",fun))#增加属性,函数和变量皆可 无返回值 20 # print(b1.__dict__) 21 # delattr(b1,"a")#删除属性 22 # print(b1.__dict__) 23 # print(hasattr(B,"a")) 24 # print(hasattr(B,"func")) 25 # getattr(B,"func")(b1) 26 # print(B.__dict__) 27 # print(getattr(B,"a"))#找不到实例变量 28 # delattr(B,"a") 29 # delattr(B,"c")#可以找到类变量 30 # print(getattr(B,"c","not exist"))
十四、__setattr__(),__getattr__(),__delattr__()属性字典操作
1 __setattr__()设置对象属性时会触发setattr,写入属性字典 2 __getattr__()调用一个对象不存在的属性时才会用 3 __delattr__()删除对象属性的时候会触发 4 5 三者都是直接操作属性字典
1 class B(): 2 def __init__(self,a,b): 3 self.a = a 4 self.b = b 5 def __setattr__(self, key, value): 6 self.__dict__[key] = value 7 # self.key = value 8 def __getattr__(self, item): 9 print("__getattr__") 10 return "not exist" 11 def __delattr__(self, item): 12 del self.__dict__[item] 13 def func(self): 14 print(self.a+self.b) 15 b1 = B(1,2) 16 17 # print(b1.__dict__) 18 19 # b1.__setattr__("sun","qi")#直接操作属性字典__dict__ 20 # print(b1.__dict__) 21 # print(b1.a)#1 22 # print(b1.c)#调用不存在的变量时才会触发getattr方法 23 24 25 # print(b1.__dict__)#{'a': 1, 'b': 2} 26 # b1.__delattr__("a") 27 # print(b1.__dict__)#{''b': 2}
十五、__getitem__(),__setitem__(),__delitem__()中括号调用属性时操作
1 __xxxitem__:使用 [''] 的方式操作属性时被调用 2 __setitem__:每当属性被赋值的时候都会调用该方法,因此不能再该方法内赋值 self.name = value 会死循环 3 __getitem__:当访问不存在的属性时会调用该方法 4 __delitem__:当删除属性时调用该方法
1 class B(): 2 c = 1 3 def __init__(self,a,b): 4 self.a = a 5 self.b = b 6 def __getitem__(self, item): 7 print("get %s"%item) 8 return self.__dict__[item] 9 def __setitem__(self, key, value): 10 print("key %s value %s"%(key,value)) 11 self.__dict__[key] = value 12 def __delitem__(self, key): 13 print("del %s"%key) 14 del self.__dict__[key] 15 16 b1 = B(1,2) 17 def func(): 18 print("func") 19 # print(b1["a"])#访问存在的变量时会调用getitem方法 20 # print(b1["d"])#访问不存在的变量时也会触发getitem方法 21 # b1["d"] = 3#设置属性时会触发setitem方法 22 # b1["func"] = func 23 # print(b1.__dict__) 24 # del b1["a"] 25 # print(b1.__dict__)#删除属性时会触发delitem方法