zoukankan      html  css  js  c++  java
  • python学习之-- 面向对象

    面向对象(简写:OOP)

    面向对象编程定义:利用类和对象来创建各种模型,来实现对真实世界的描述。

    优点:使程序更容易理解和维护以及扩展代码。

    类定义:用来描述具有相同的属性和方法的对象的集合。(简单讲就是个模板)

    实例化定义:创建一个类的实例,类的具体对象。

    对象定义:通过类定义的数据结构的实例

    举例:一个最简单最小结构的类写法如下:

    class class_name(object):
        print('bababa')

    举例一个正常类的写法:

    class 类名称(object):
        def __init__(self,name..) #构造函数
            self.arg1 = name # 普通属性(成员变量),注:self就是实例对象本身,保存在对象内存里
        def fun1(self): # 普通方法(动态属性)
            print('...')

    类进行实例化的运行原理:

      1:将类中的对象和方法存储于内存中,
      2:类进行实例化时,先在内存申请一块空间用于存放实例对象
      3:把实例对象的内存地址和赋值参数传递给类模板
      4:模板对传入的值进行self变量赋值,然后将self变量发送到实例对象内存空间。

    类的三大特性:封装,继承,多态

      -- 封装:类内部的数据和方法,对数据的赋值和内部调用对类外部而言是透明的。简单说就是隐藏实现的细节,使代码模块化。

          特性:防止数据被随意修改,可以通过此对象对外接口进行直接访问。

           另(类封装了属性和方法,对象封装了普通属性的值)

      -- 继承:一个父类派生出的子类,在父类里定义的属性和方法自动被子类继承,实现一个角色的共同点和不同点的同时存在。使代码重用

          注意:承可以多级继承,不过越多代码会越复杂,建议继承2-3级即可,继承的2个类之间应该是属于的关系。

        -- 被继承的类命名:父类,基类,超类

        -- 继承的类命名:子类,派生类

          --种类:单继承和多继承。

          --继承的过程:从一般到特殊的过程。

                 这里“一般”指:父类这样的对一个角色具有共同点。

                 这里“特殊”指:子类这样的对每一个角色的不同点的单独定义

          --实现方式有2类:实现继承 和 接口继承

                 实现继承:指父类具有的功能,子类继承后直接调用不需再修改。

                 接口继承:指仅使用父类的属性和方法的名称,具体实现需要在子类里单独实现。

    举例:单继承基本继承写法

     1 class Person(object):
     2     def __init__(self,name,age=22):
     3         self.NAME = name
     4         self.AGE = age
     5         self.storage = 'Normal'
     6     def talk(self):
     7         print('custom ......')
     8 class blackPerson(Person):
     9     def __init__(self,name,age,job):
    10         Person.__init__(self,name,age)  #继承父类的属性(经典写法)
    11         self.JOB = job
    12     def talk(self):
    13         Person.talk(self)   # 继承父类的方法,不过这样没有意义,
    14         print('非洲语言')
    15 class writePerson(Person):
    16     def __init__(self,name,mess):
    17         Person.__init__(self,name)
    18         self.MESS = mess
    19     def talk(self):
    20         print('speak ENGLISH')
    View Code

     -- 多态:同样的方法名的同时又对父类的方法做了不同的实现,这就是同一事务表现的多种形态。特点接口重用。

         (举例:父类定义人会说话,子类分黄种人说汉语,白种人说英语)这就是多态。实现是改写父类的talk方法

    举例:python中多态的写法

     1 class Animal(object):
     2     def __init(self,name):
     3         self.name = name
     4     def talk(self):
     5         raise NotImplementedError('Subclass must implement abstrace method') #提示一个需要子类重写的错误
     6 class Cat(Animal):
     7     def talk(self):  # 子类重写
     8         return 'miao'
     9 class dog(Animal):
    10     def talk(self):  # 子类重写
    11         return 'wang'
    12 d = dog()
    13 c = Cat()
    14 def animal_talk(arg):  # 这里使用单独一个函数实现多态功能
    15     return arg.talk()
    16 print(animal_talk(d))
    17 print(animal_talk(c))
    View Code

    类的属性分如下:

      -- 公有属性(静态字段):所有属于这个类的对象都可以访问的属性,(在类里直接定义的属性,class下一行定义的)

           修改方法:1:通过对象修改,只改变该对象的属性值,相当于在对象本地内存新创建一个属性值(默认是引用类里的全局变量)

                2:通过“类.公有属性名”修改,将改变的是全局属性值。

                (疑问解释:类中的构造函数不都可以访问么,说的是实例对象,一个实例对象赋给的参数值在其他对象是无法访问的。所以构造函数不属于公有属性。

                      比如:实例化了2个对象a,b,其中实例化a的参数值(a=fun(1,2,3)),对象b就无法访问a的参数值。)

      --成员属性(普通字段):构造函数中的self变量。

      --私有属性:在类中以“__字符串”,双下划线开始的变量名即为私有属性。正常情况下私有属性在类外部是无法访问的。

         访问方法有2种:1:通过在类里定义普通方法来return返回私有属性。2:强制访问写法:实例名._类名__私有属性名。

              举例:使用第一个方法对外提供私有属性访问接口

                  def get_hart():

                    return self.__heart  #这里就直接返回私有属性值

    类的方法分如下:

      -- 普通方法:类中定义的常用方法。def定义的

          小知识(如何将普通方法变为私有方法,1:单独写一个函数,比如名为fun2,然后重写对象的方法名,如d1.fun = fun2,最后执行此对象的方法d1.fun(d1))

      -- 析构方法:语法:def __del__(self),在引用的变量被清空的时候或者通过手工del删除引用的变量后就会自动调用此方法进行内存回收。

          一般用于程序的收尾,比如服务器端要停止服务,这时就需要它来清空客户端的连接。(另说明,只要类被实例化了就算是使用中,将不会自动回收)

      -- 类方法:只能访问类变量(公有属性),不能访问实例变量,一般用在实例化对象后,无法对本身限定好的数据进行修改。

            举例说明:          

                class f1:
                  name = 'jack'  #类变量
                  @classmethod #类方法
                  def fun(self):
                    print('classmethod %s' % self.name) # 这里数据只用使用name的值,无法修改

      -- 静态方法:类里定义的方法,当不需要通过self往里传值的时候,就可以将此方法定义为静态方法。

            举例说明:

                class f1:
                  @staticmethod  # 静态方法写法
                  def fun():     # 注意 静态方法是不需要self传值,这里不写self
                  print('staticmethod')
                调用方法为: f1.fun()

      -- 属性方法:把一个方法变成一个静态属性,属性就不需要加括号调用,一般用于最终展示给用户看得结果  

            举例说明:

                class f1:
                  def __init__(self):
                    self.__food = None # 为属性方法设置的私有属性(用于传值的,如果不使用setter方法,就可以不写)
                  @property #属性方法 (静态属性)默认这里只能打印固定数据,无法赋值
                  def fun(self): # 方法名
                    print('property: %s' % self.name,self.__food)
                  @fun.setter # 实现对属性方法赋值功能(注意这里的fun要和上面的方法名一致)
                  def fun(self,food):
                    print('set to food:',food)
                    self.__food = food    # 实现对私有属性的赋值
                  @fun.deleter # 实现删除属性方法的赋值
                  def fun(self):
                    del self.__food # 删除私有变量

                调用方法:d = f1() ; d.fun # 打印属性方法
                赋值方法:d.fun = 'baozi' # 赋值
                删除赋值:del d.fun #删除

      -- 内置方法:类里以:__名称__  这样结构的方法称为类的内置方法。

            1:__doc__:类的描述信息,就是打印类名下的注释信息
            2:__module__:表示当前操作的对象在哪个模块
               __class__:表示当前操作的对象的类名
            3:__init__:构造函数,通过类创建对象时,自动触发执行。
            4:__del__:析构函数,当对象在内存中被释放时,自动触发。
            5:__call__:对象后面加括号,触发执行。

                举例说明:

                  class cla1(object):
                    def __call__(self, *args, **kwargs):
                      print(args,kwargs)
                  ins = cla1()
                  ins('jace','vivi',name='jack',age=22)  # 这里执行对象直接返回
                  返回:('jace', 'vivi') {'name': 'jack', 'age': 22}        

            6:__dict__:查看类或对象中的所有成员
                print(类名.__dict__):打印类里的所有属性,不包括实例属性。print(实例名.__dict__):打印实例里所有的属性,不包括类属性
            7:__str__:如果一个类中定义了此方法,那么在打印实例对象时,默认输出该方法的返回值

     1 class Person(object):
     2     def __init__(self, name, gender):
     3         self.name = name
     4         self.gender = gender
     5     def __str__(self):
     6         return '(Person: %s, %s)' % (self.name, self.gender)
     7 现在,在交互式命令行下用 print 试试:
     8 
     9 >>> p = Person('Bob', 'male')
    10 >>> print p
    11 (Person: Bob, male)
    View Code

            8:__repr__:在python3里发现直接运行实例和使用pring 输出的状态和__str__ 相同。没看出有什么区别。但是通过sqlalchemy的创建表结构里可以看出区别,

                     通过在表结构里定义__str__返回来的数据是内存对象,通过在表结构里定义__repr__返回来的是转换后的字符串。

            9:__getitem__ / __setitem__ / __delitem__ :用于索引操作,分别表示获取,设置,删除数据。

                举例说明:

     1 class cla1(object):
     2     def __init__(self):
     3         self.data = {}
     4     def __getitem__(self, key):
     5         print("__getitem__: %s" % key)
     6         return self.data.get(key)
     7     def __setitem__(self, key, value):
     8         print('__setattr__:%s,%s' % (key,value))
     9         self.data[key] = value
    10     def __delitem__(self, key):
    11         print('__delitem__:%s' % (key))
    12 ins = cla1()
    13 ins['name'] = 'jack'  #调用setitem赋值
    14 print(ins['name']) # 调用getitem打印
    15 print(ins.data)   # 打印实例属性
    View Code        

            10:__new__:先于构造函数执行,构造函数是通过New来自动执行的。所以new是用来创建实例的,默认不用写
                 用处:可以在类进行实例化之前,通过new进行定制

    1 class foo(object):
    2     def __init__(self,name):
    3         self.name = name
    4         print('foo --init--')
    5     def __new__(cls, *args, **kwargs):
    6         print('foo --new--')
    7         return object.__new__(cls) # 继承父类的new方法,如果注销这个,将不会自动执行构造函数,
    8         #以上这行解释,类foo也是一个对象,这里的cls就是foo对象本身,也就相当于self概念。
    9 f = foo('jack')
    View Code

            11:__metaclass__ : 指定当前类的原类名称,可以修改原类对当前类进行重新设置。在上面的new执行之前,
              执行顺序为:第一步执行metaclass的init方法,第二步执行metaclass的call方法,第三步执行foo函数的new方法,第四步执行foo的initd方法,

                    这就是实例化整个路线图。
                看代码:

     1 class Mytype(type):
     2     def __init__(self):                #第一步
     3         super(Mytype.self).__init__(what,bases,dict)
     4     def __call__(self,*args,**kwargs):        #第二步
     5         .....
     6 class foo(object):
     7     __metaclass__ = 'Mytype'
     8     def __init__(self,..):            # 第四步 实例化完成
     9         .....
    10     def __new__(cls,*args,**kwargs):
    11         return object.__new__(cls)        #第三步
    View Code

                看图:

    类的 分类:有2种,第一种是:新式类。第二种是:经典类

      -- 他们的区别:1:新式类需要在类名后加(object),经典类不需要,直接定义类名。2:继承方式写法不同。

      -- 继承方式:在Python3中全部(新式类/经典类)为广度优先,在Python2中经典为深度优先,新式类为广度优先。

      -- 继承写法:新式类使用super,经典类直接使用父类名初始化。

            举例说明:

                class A(object):
                  def __init__(self):
                    self.n = 'A'
                class B(A):
                  def __init__(self):
                    self.n = 'B'
                class C(A):
                    def __init__(self):
                    self.n = 'C'
                class D(B,C):
                  pass

                mess = fun4() ; print(mess.n)
    解释:在python3中,无论是新式类还是经典类,继承顺序都是广度优先,以上顺序为:B->C-A
         在python2中,新式类继承顺序为广度优先,如上,经典类是深度优先为:B->A->C

    举例单独说明类中的self。(self == 实例对象)

    class dog(object):
      def __init__(self,name):
        self.NAME = name
      def sayhi(self):
        print('wang wang wang , dog name %s' % (self.NAME))

    dg1 = dog('jinba')  # 相当于:dog(dg1,'jinba') 注意:self == dg1(实例对象)
    dg1.sayhi()     #  就相当于:dg1.sayhi(dg1),因为self在类中默认是传入的。

  • 相关阅读:
    MSSQL转MySql
    MVC 4中的坑
    IIS错误记录
    MongoDB C#备忘
    IL指令集 收藏【转载】
    使用aforg.net 录制摄像头 附源码
    使用aforg.net 捕获摄像头 附源码
    Tesseract parameters in 3.02 version
    Unity平台宏定义
    unity3d杂录【2】
  • 原文地址:https://www.cnblogs.com/zy6103/p/6911663.html
Copyright © 2011-2022 走看看