Python有两种编程方式:函数式+面向对象
函数式编程可以做所有的事情,但是否合适?
面向对象:
一、定义
函数:
def + 函数名(参数)
面象对象:
class bar---> 名字叫bar的类
def --->类中的函数叫方法
二、执行
函数:
函数名(参数)
面向对象:
obj = Bar() #创建中间人(对象、实例)
obj.foo
定义类并执行类中的方法:
class 类名: #类名后面没有括号
def 方法名(self,args)
print(args)
中间人 = 类名( )
中间人.方法名(1111)
class bar: #类名后面没有括号 def foo(self,args): print(args) obj = bar() #定义对象的时候需要加括号 obj.foo('this is the test')
类里面的方法也有return值
类对象指针
self
self代指,调用方法的对象(中间人)
构造方法:
特殊作用:
在执行obj = 类名()时,一共做了两件事:
1、创建对象
2、通过对象执行类中的一个特殊方法(构造方法)
面象对象的三大特性之一:封装
利用构造方法将值封装到对象中去。
class person: def __init__(self,name,age): """ 构造方法,构造方法的特性,类名()自动执行构造方法 :param name: :param age: """ self.n = name self.a = age def show(self): print('%s-%s'%(self.n,self.a)) #格式化字符,%s一定是要放在字符串中 lihuan = person('李欢',18) lihuan.show()
面向对象编程适用场景:
如果多个函数中有一些相同参数时,转换成面向对象
面象对象三大特性之二:继承
class F: #父类,基类 def f1(self): print("F.f1") def f2(self): print("F.f2") class S(F): #子类,派生类,定义子类的时候后面要加括号,括号中写上父类名称 def s1(self): print("S.s1") s = S() s.s1() #方法后面有括号,s1中的self是形参,此时代指s s.f1() #self用于指调用方法的调用者
#如果不想继承父类中的方法怎么办?(自己定义一个一样的方法,也叫重写) class F: #父类,基类 def f1(self): print("F.f1") def f2(self): print("F.f2") class S(F): #子类,派生类 def s1(self): print("S.s1") def f2(self): print("S.f2") obj = S() obj.s1() obj.f2() #此时调用的就是S中的f2方法,父类的同名方法不执行
#如果既想调用自己的f2,又想调用的父类的f2,怎么办? class F: #父类,基类 def f1(self): print("F.f1") def f2(self): print("F.f2") class S(F): #子类,派生类 def s1(self): print("S.s1") def f2(self): super(S, self).f2() #执行父类中f2方法的第一种方式,括号内为固定格式,这里不仅仅可以用此方式调用f2,也可以调用f1 F.f2(self) #执行父类中f2方法的第二种方式,括号里的self一定要加,建议用第一种 print("S.f2") obj = S() obj.f2() #如果想执行自己和执行父类的顺序改变一下,定义方法的时候改变一下顺序就OK了
在Python中支持多继承,查找顺序如下:
1、左侧优先
2、一条道走到黑
3、如果有同一个根时,根最后才执行
class RequestHandler(): def serve_forever(self): print('RequestHandler.serve_forever') self.process_request() #执行这个的时候,还是从原点开始找 def process_request(self): print('RequestHandler.process_request') class Minx(): def process_request(self): print('Minx.process_request') class son(Minx,RequestHandler): pass obj = son() obj.serve_forever()
由于实例化的时候会自动执行__init__方法,所以如果实例化的类中没有__init__方法,它也会按照上面的方法去寻找,这一点一定要注意,因为这是自动执行的,所以很容易被忽略。
面向对象三大特性之三:多态
------------------->>>>Python原生就是多态的。
类成员:
-字段
-方法
-属性
字段:
普通字段,保存在对象中,只能通过对象访问
静态字段,保存在类中,可以通过对象访问,也可以通过类访问
class province: #静态字段,属于类,可以通过类访问,也可以通过对象访问 country = '中国' def __init__(self,name): #普通字段,属于对象,只能通过对象访问 self.name = name print(province.country) #中国 hebei = province('河北') print(hebei.name) #河北 print(hebei.country) #中国,静态字段是可以通过对象访问的
方法:
普通方法,保存在类中,由对象来调用,self是对象
静态方法,保存在类中,由类直接调用,不用self参数
类方法,保存在类中,由类直接调用,cls是当前类
class Foo: def bar(self): print('bar') @staticmethod #静态方法加的装饰器 def sta(a1,a2): #静态方法中括号内不用加self,可以没有参数,也可以设定其它参数,这样的话,类在调用方法的时候,就不用传参数了,这样就不用创建对象,就可以直接调用方法 print(a1,a2) @classmethod #类方法 def classmd(cls): #这个cls和self一样,python都会自动传 print('classmd') obj = Foo() Foo.bar(obj) #这是类调用方法的,需要加参数self,所以必须要创建对象才行 Foo.sta(1,2) Foo.classmd()
####### 应用场景:
如果对象中需要保存一些值,执行某功能时,需要使用对象中的值----->普通方法
不需要任何对象中的值,静态方法
class Foo: @property #创建属性(特性) def per(self): print('123') obj.per #虽然是方法,但执行的后面却不加括号
class Foo: @property def per(self): return 1 @per.setter def per(self,val): # 这块的函数名必须和上面装装饰器的名称一致,不然报错。Names of function and decorator don't match print(val) @per.deleter def per(self): print(666) @per.getter def per(self,val): print(val) obj = Foo() res = obj.per print(res) # 1 obj.per = 100 # 100 del obj.per # 666