zoukankan      html  css  js  c++  java
  • 面向对象编程——类(class)1

    一、函数式编程 与 面向对象编程

    def 函数名(参数):
        pass
    
    
    class 类名:
        def 函数名(self,参数):       # self必填
            pass
    
    z1 = 类名()    # 这时,调用对象 z1,self参数即为 z1
    

    例1:

    class bar:
        def foo(self,arg):
            print(self,arg)
    
    z1 = bar()
    print(z1)               # <__main__.bar object at 0x0000019BC3088D30>
    z1.foo('wjz')           # <__main__.bar object at 0x0000019BC3088D30> wjz
    
    z2 = bar()
    print(z2)               # <__main__.bar object at 0x0000019BC306B358>
    z2.foo('wjk')           # <__main__.bar object at 0x0000019BC306B358> wjk
    

    从上面的例子可以看出,self 就是当前调用的对象(即使后面继承时);

    例2:

    class bar:
        def foo(self,arg):
            print(self.job,arg)
    
    z1 = bar()
    z1.job = 'IT'
    z1.foo('wjz')           # IT wjz
    
    z2 = bar()
    z2.job = 'IT'
    z2.foo('wjk')           # IT wjk    
    

    从上面可以看出,当向对象存储变量时,它会把该变量传给类里面的方法;

    二、面向对象三大特性:封装、继承、多态

    1. 封装

    构造方法:

    当 obj = 类名()  时,实际上是做了两件事:
        在内存中开辟空间,创建对象;
        通过对象,自动执行了一个方法:__init__方法(别名:构造方法)。
    

    把公用的变量封装到init方法中。 例如:

    class DataBaseHelper:
        def __init__(self,ip,port,username,password):
            self.ip = ip
            self.port = port
            self.username = username
            self.password = password
    
        def insert(self):
            pass
    
        def delete(self):
            pass
    
        def update(self):
            pass
    
        def select(self):
            pass
    

    适用场景:如果多个函数都用一些共同参数,则适合面向对象来做。例如上面数据库操作;

    2. 继承

    举例:

    class f:
        def f1(self):
            print("in the f.f1")
    
    class s(f):                     #这里加一个括号,指明该类的父类(基类);子类(派生类)会继承父类的方法;s类中找不到发方法,会去f类中找。
        def s1(self):
            print("in the s.s1")
    
        def f1(self):
            super(s,self).f1()      # 这里super(s,self) 表示是s的父类;
            f.f1(self)              # 这个等效上面这句 super(s,self).f1();注意,一定不能忘记self          
            print("in the s.f1")
    
    z = s()
    z.f1()
    

    多继承: 如果子类继承多个父类,则排在前面的父类优先;如:

    class father1:
        def a1(self):
            print("in the f1.a1")
    
    class father2:
        def a1(self):
            print("in the f2.a1")
    
    class son(father1,father2):         # father1在前面,优先继承;
        def s1(self):
            print("in the son.s1")
    
    z = son()
    z.a1()                  # 等效 son.a1(z)  打印 in the f1.ar   此时,father1和father2都有a1方法,并且son的父类有两个,则按顺序优先。
    

    上面例子中,假如father1中没有a1方法,而father2有。但是father1的父类有a1,则继续在father1的父类中查找。都没有时,才会去father2。但是,如果father0是father1和father2共同的父类,则会最后继承共同的父类。如图:

    3. 多态

    python中,原生多态。这个不重要,先忽略吧。

    三、 类

    类成员

    类(class)的成员有字段、方法;其实还有一个属性

    • 字段分为静态字段、普通字段;
    • 方法分为构造方法、静态方法、普通方法、类方法;

    1. 字段

    在类中定义的变量,称为静态字段,属于类,保存在类中,可以通过类或者对象访问;

    在类中的方法中定义的字段,称为普通字段,属于对象,保存在对象中,只能通过对象访问;

    如下:

    • class make:
          port = 22                       # 静态字段
          def __init__(self,ip,username,passwd):
              self.ip = ip                # 普通字段
              self.username = username
              self.passwd = passwd
      
      z1 = make('1.1.1.1','root','123456')
      print(z1.ip,z1.username,z1.passwd,z1.port)      # 打印 1.1.1.1 root 123456 22
      
      z2 = make('2.2.2.2','admin','admin')
      print(z2.ip,z2.username,z2.passwd,z2.port)      # 打印 2.2.2.2 admin admin 22
      
      print(make.port)                                # 打印 22      可见,静态字段属于类,同时也可以通过类对应的对象取得(因为对象通过类对象指针指向该类)。
      

    2. 方法

    构造方法:在上面面向对象三大特性之封装章节已经提到,即init方法;self是必须的;

    普通方法:和构造方法一样,只是名字不是 init的方法就是普通方法;由对象调用,也可以通过类进行调用(必须指定self对象),self是必须的;

    静态方法:在普通方法前面加上装饰器 staticmethod,即是静态方法;但是有个区别:self不是必须的;普通方法调用时,self就是当前调用对象;而静态方法中,如果指定了self,则必须指定self才可以;由类或对象(对象调用其实是根据类对象指针,通过类进行调用)调用;

    类方法:在普通方法前面加上装饰器 classmethod,即是类方法;类方法中,一般不使用self,而是写成 cls,cls为当前类;由类直接调用;类方法和静态方法没有太大区别;

    例如:

    • class make:
      
          def __init__(self):         # 构造方法
              pass
      
          def upload(self):           # 普通方法
              pass
      
          @staticmethod
          def status(self):           # 静态方法,self不是必须的,可以不要self;
              pass
      
          @classmethod
          def classmd(cls):           # 类方法,这里一般写cls
              print(cls)
              pass
      
      make.classmd()              # 打印结果和 print(make)一样。
      

    3.属性

    说类的成员有两种。其实还有一种,定义像方法,调用像字段;我们叫它 属性

    这种属性还可以修改、删除;其实并不是真的删除,只是伪造字段的操作(修改、删除)

    • class make:
      
          @property
          def its(self):              # 定义属性,如果定义了property之后,后面还有getter,则优先执行getter;如果没有定义getter,则调用时执行property
              print("property")
              return 1
      
          @its.getter
          def its(self):              # 优先级高于property;
              print("getter")
      
          @its.setter
          def its(self,value):              # 定义属性its可以修改
              print(value,"setter")
      
          @its.deleter
          def its(self):              # 定义属性its可以删除
              print("delete")
      
      obj = make()
      r = obj.its                 # obj.its像是调用字段,但是its定义时像方法;
      print(r)                # 返回 1
      
      obj.its = 123456            # 看似是更改,其实是找到 its.setter,然后执行。123456当做参数传给 its.setter
      
      del obj.its                 # 看似是删除,其实是找到its.deleter,然后执行
      

    在上面的基础上补充:

    class make:
        @property
        def f1(self):
            print("in the f1")
            return 123
    
        @f1.getter
        def f1get(self):
            print("in the f1getter")
            return 00
    
        @f1.setter
        def f1set(self,value):
            print("in the f1setter",value)
            return 11
    
        @f1.deleter
        def f1del(self):
            print("in the f1deleter")
            return 22
    
        @f1get.fget                     # 这里可以执行 @property修饰的方法f1;
        def f2(self):
            print("in the f2")
            return 456
    
        @f1set.fset
        def f3(self):
            print("in the f3")
            return 789
    
        @f1del.fdel
        def f4(self):
            print("in the f4")
            return 000
    

    我们不调用类,只是定义这个类,这时:

            @f1get.fget 会自动执行 f1get方法;

            @f1set.fset 会自动执行 f1set方法;

            @f1del.fdel 会自动执行 f1del方法;

    三个是相同的原理,注意:fget可以执行 property、getter的对象;fset只可以执行setter的对象;fdel只可以执行deleter的对象。

    这里就拿fget举例:

    另外:

    def f1(self):
        return 123 
    per = property(fget=f1)
    
    ------ 上下两部分等效 ------
    
    @property
    def per(self):
        return 123
    

    同理,

    class make:
    def f1(self):
        print("in f1")
        return 123
    
    def f2(self,val):
        print("in f2",val)
        return 456
    per = property(fget=f1,fset=f2)         # 这里就是关键字参数,fget/fset可以省略,就是位置参数;即,fget、fset、fdel顺序。property(fget,fset,fdel,doc="描述")
    
    z = make()
    z.f1 = 123
    
    ------ 上下两部分等效 ------
    
    class make:
        @property
        def f1(self):
            print("in f1")
            return 123
    
    
        @f1.setter
        def f1(self,val):
            print("in f2",val)
            return 456
    
    z = make()
    z.f1 = 123
    如需转载,请注明出处,否则本人会追究法律责任!
  • 相关阅读:
    libevent源码学习之event
    游戏寻路A*算法
    游戏地图动态生成
    一个基于protocol buffer的RPC实现
    TCMalloc源码学习(四)(小内存块释放)
    TCMalloc源码学习(三)(小块内存分配)
    TCMalloc源码学习(二)
    第五十四篇 Linux相关——远程连接SSH
    第五十三篇 Linux相关——Web服务器
    第五十二篇 Linux相关——数据库服务MySQL
  • 原文地址:https://www.cnblogs.com/hacker001/p/10094783.html
Copyright © 2011-2022 走看看