面向对象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。

 

静态字段:

class A:
  haha = "hahaha" #静态字段
  def __init__(self, name):
    print("AAAAAA")
    self.name = name #普通字段

b = A("aa")
print(b.haha)
或者:
print(A.haha)
输出:hahaha

输出: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"

 

posted @ 2018-09-13 10:31  greenfan  阅读(142)  评论(0)    收藏  举报