面向对象1
1、面向对象不是所有情况都适用
适用场景:当同一类型的方法具有相同参数时,直接封装到对象即可。
把类当作模版,创建多个对象(对象内封装的数据不一样)
2、面向对象编程
a.定义类
class Foo:
def 方法1(self,bb):
pass
b.根据类创建对象(创建一个Foo的实例)
使用对象去执行方法
3、self,形式参数,代指执行方法的对象。python内部传递
obj = Foo()
obj.fetch("bb") #此时self指obj
4、类+括号--->自动执行类中的__init__方法,在__init__方法中执行具体封装的操作,__init__有一个特殊名字叫构造方法
class Foo:
def __init__(self,bk):
self.name = "alex"
self.favor = bk
obj1 = Foo("xx")
obj2 = Foo("oo")
class Oldboy:
def __init__(self, bk):
#构造方法
self.backend = bk
def fetch(self):
print(self.backend)
def del_recodrd(self):
print(self.backend)
#创建对象,并将“www.aaaa.com”封装到对象中
obj = Oldboy("www.aaaa.com")
obj.fetch()
关于继承:
可以继承多个类(c#、Java不可以),如果父类同时包含同样的方法,优先顺序是执行当前子类的方法,如果当前子类没有方法,两个父类却有同样的方法,则执行第一个父类的方法。注意:如果e继承了两个父类c和d,c继承了a,d继承了b,如果一个方法在a和b中都有,其它类都没有,那么会执行a中都方法。但是如果a和b又同时继承类一个父类x,那么顺序为:c-a-d-b-x,就是子类所继承的两个父类都继承类同一个类e,则e最后找。
class father:
def __init__(self, name):
self.name = name
def eat(self):
pass
def dream(self):
pass
class mother:
def drink(self):
pass
def dream(self):
pass
class son(father,mother):
def fuck(self):
pass
def dream(self):
pass
PS:obj执行f1(),因为D中没有,找到了B中的f1(),先打印“B”,还没执行完,下面还有一个self.f2(),注意这个self.f2()并不是执行类B父类中的,而是执行类C中的f2(),因为需要记住的重点是此处的self.f2()中的self是指obj对象,所以它会在obj中按照优先顺序找到C中的f2()
class A:
def f2(self):
print("A")
class B(A):
def f1(self):
print("B")
self.f2()
class C:
def f2(self):
print("C")
class D(C,B):
pass
obj = D()
obj.f1()
输出:B
C
面向对象都三大特性:封装、继承,还有一个多态
关于多态:python原生支持多态,比如c#、Java的类,
class test: def f1(self): pass class test2: def f1(self): pass
python:arg参数可以是test,也可以是test1,这就是多态
def aa(arg): arg.f1() aa(test) aa(test1)
c#、java:agr必须是test类创建的对象,这样就不可以传test1做参数了。但是可以让test1继承test,那么就可以了,就叫多态
def aa(test arg): arg.f1()
在其它c# Java中还有重载、重写的名词,重载是一个类中,函数名相同,但是参数不同,这点python不支持。
重写就是子类如果有跟父类相同的方法名,就叫重写。
super:执行父类的构造方法:
class A: def __init__(self): print("AAAAAA") class B(A): def __init__(self): print("BBBBB") obj = B()
输出:BBBBB
class A: def __init__(self): print("AAAAAA") class B(A): def __init__(self): super(B,self).__init__() print("BBBBB") obj = B()
输出:AAAAAA,BBBBB
或者:
class A: def __init__(self): print("AAAAAA") class B(A): def __init__(self): print("BBBBB") A.__init__(self) obj = B()
输出:BBBBB,AAAAAA [ super(子类,self).__init__() == 父类.__init__(self) ],执行父类的构造方法,推荐用super。
静态字段:
输出:AAAAAA hahaha,这个静态字段存在类中,并不会在每一个实例对象中创建,但是可以在对象中调用,所以在创建多个对象,并且所有对象都有一个共同值的时候可以使用,以避免在每个对象中都创建一个重复变量。静态字段是类都成员,所有访问都时候尽量用类去访问,因为此方法在Java、c#中也可以,但是通过对象访问,它们可能就不可以了。
虽然都可以访问,但是尽量坚持以下原则:
通过类访问:静态字段,静态方法,类方法
通过对象访问:普通字段,类的方法
解释一下什么是静态方法:
class A: haha = "hahaha" #静态字段 def __init__(self, name): print("AAAAAA") self.name = name #普通字段
#静态方法:可以传参数,但是没有self @staticmethod def xx(arg1): print(arg1) A.xx("oo")
xx方法没有self,在它上面加一个@staticmethod,xx就是一个静态方法了。
c、java中,类只能访问静态字段和静态方法,对象只能访问普通字段和普通方法,所以为了将来使用其它语言,尽量保持这个习惯。
静态方法可以不用创建对象,直接用类调用,相当于一个将一个普通函数封装到一个类中。
解释一下类方法:
class A: haha = "hahaha" #静态字段 def __init__(self, name): print("AAAAAA") self.name = name
#加上@classmethod装饰器,xx就是一个类方法 @classmethod def xx(cls): print(cls) print(A.xx())
输出:<class '__main__.A'>,在调用A.xx()这个类方法到时候,并没有传参数‘cls’,但是它自动把类名当参数传进去了。就是说类方法可以获取当前类的类名。
@property,一个方法执行的时候,需要加(),如果加上@property装饰器,那么执行这个被装饰的方法时,就不需要加()了,当然也不能传递参数了。也就是相当于将方法伪装成一个字段,因为字段是不需要加()的,类如:b = A.name
class A: def __init__(self, name): self.name = name def xx(self): print(self.name) @property def oo(self): print(self.name) ret1 = A("wow") ret1.xx() ret1.oo
继续讲解@property:
class A: def __init__(self, name): self.name = name def xx(self): print(self.name) @property def oo(self): return(self.name) @oo.setter def oo(self,arg): print(arg) obj = A("wow") obj.oo = "123"
输出:123
第一个oo是用来获取oo的值,第二个oo可以用来设置参数。PS:第二个oo最后一行'print(arg)',试着写成'return (arg)',并不能拿到新传的值‘123’,但是‘print’可以打印出来,暂时没搞懂。
搞懂了,因为第一个oo返回的是self.name,所以第二个oo中修改了self.name,第一个oo再获取的时候自然就会改变了,上面的例子中,第二个oo虽然传了一个值,但是那个参数跟self.name毫无关系,才导致obj.oo = "123"后,再运行print(obj.oo),结果不变,因为obj.oo = "123",根本就没有修改self.name的值
class A: def __init__(self, name): self.name = name def xx(self): print(self.name) @property def oo(self): return(self.name) @oo.setter def oo(self,arg): self.name = arg obj = A("wow") print(obj.oo) obj.oo = "123" print(obj.oo) obj.oo = "456" print(obj.oo)
输出:
wow
123
456
成员修饰符:python中有两种成员修饰符,一种是公有,一种是私有,在成员前面加"__"会使成员变成私有成员
class A: xx = "xx" __oo = "oo" def __init__(self, name): self.name = name def aa(self): print(self.name) obj = A("wow") print(obj.xx) #输出:xx print(obj.__oo) #报错,A没有__oo属性
想要访问这种修饰符,只有此类中的方法可以访问,其子类也不可以访问:
class A: xx = "xx" __oo = "oo" #私有成员 def __init__(self, name): self.name = name def aa(self): print(self.name) print(A.__oo) obj = A("wow") obj.aa() #输出:"oo"
同理,在方法前加__,方法也会变成私有方法,也只有此类中的其它方法可以调用。
普通方法变私有成员,可以通过类内其它方法访问:
class A: def __aa(self): print("this is __aa") def test(self): self.__aa() obj = A() obj.test()
输出:this is __aa
静态方法变私有成员,可以通过类内其它方法访问:
class A: @staticmethod def __aa(): print("this is __aa") def test(self): self.__aa() obj = A() obj.test()
输出:this is __aa
可以通过一个方法访问私有成员,但是不建议使用此方法,仅做了解:
class A: __wow = "wow" def __init__(self): self.__name = "123" obj = A() print(obj._A__wow) #输出:"wow" print(obj._A__name) #输出:"123"

浙公网安备 33010602011771号