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

    1面向过程编程
    固定的目的 固定的结果
    从头到尾把要执行的步骤堆积出来就好了
    2面向对象编程
    有一个抽象的过程
    上帝视角:结果不能预测

    第一步 认识类

    类的定义
    class 类名:
            静态属性 = '值'
            def 方法(self):
            pass

    #类:静态属性 动态属性
    #类可以调用静态属性
    #类可以查看动态属性 却必须要带上具体的对象参数才能调用动态属性
     1 class Person:
     2     rol = ''                                 #数据属性、静态属性、类属性
     3     country = '中国'
     4     def __init__(self,name,age,life_value):   #初始化方法
     5         # self.__dict__['name'] = name
     6         self.name = name                      #属性、对象属性
     7         self.theage = age
     8         self.life_value = life_value
     9         self.aggr = 200
    10     def attack(self):                         #函数属性、动态属性、方法
    11         #self只是一个形式参数,可以叫其他名字,但正常没人会这样
    12         #self是水性杨花,那个对象调这个方法,self就是那个对象
    13         print('attack方法被%s执行了'%self.name)

    对象 

    对象可以有自己的对象属性,可以调用类的方法

    对象 = 类名()                       实例化
    对象.静态属性 ----------------- 获取类的静态属性

    对象.属性 ----------------------------- 说的是__init__的里面属性

    self.name = name       #属性、对象属性
    self.theage = age
    self.life_value = life_value


    对象.方法             #可以调用不能执行 必须加括号才能执行

    对象.方法()         这种形式的本质是          类.方法(对象)

    对象.方法() 仅仅是 简写

     1 class Dog:
     2     def __init__(self,name,type):
     3         self.name = name
     4         self.dog_type = type
     5         self.life_value = 2000
     6 
     7     def bite(self,name):
     8         print('%s咬了%s'%(self.name,name))
     9 
    10 旺财 = Dog('旺财','土狗')
    11 #使用init去进行属性的初识化
    12 #1.规范所有的对象都拥有一些基础的属性
    13 #2.方便

    第二部 认识对象 对象是基于类实例化出来的。是有血有肉有属性的

    类加上括号的过程: 我们把类加上加上括号产生对象叫做实例化
    1.先创建了一个对象 self = {}
    2.才执行初始化方法__init__,同时把创建的对象扔到了__init__参数里

    #类有属于自己的命名空间
    #对象也是
    #类不可以调用对象的属性
    #对象在寻找属性的时候,是先找自己名称空间的,找不到就找类名称空间里的.

    类中定义的函数(没有被任何装饰器装饰的),其实主要是给对象使用的,而且是绑定到对象的,虽然所有对象实例化后相同的功能,但是绑定到不同的对象就是不同的绑定方法

    强调:绑定到对象的方法的特殊之处在于,绑定给谁就由谁来调用,谁来调用,就会将‘谁’本身当做第一个参数传给方法,即自动传值(方法__init__也是一样的道理)

    属性修改

    一说静态说行就是类属性

    对于任何数据类型(列表,字符串,数字)的静态属性:他的修改操作尽量用类名
    尤其是对于不可变数据类型:修改必须用类名

    类和对象都可以使用--- 名称.属性=变量     的方式修改自己的属性

    对象还可使用 点__dict__['name']='sobey' 来修改属性 但是 类不可以

    第三部分继承与派生

    什么是继承

    继承指的是类与类之间的关系,是一种什么是什么的关系,功能之一就是用来解决代码重用问题

    继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类

     继承

    子类继承父类的方法和属性

    class A:
        tag="123"
        __name="xiaoming"
        def foo(self):
            print(self.__name)
    
    class B(A):
        def ppp(self):
            print("b")
    b=B()
    b.foo()
    print(b.tag,"123123123")

    多继承

     1 class Water1: #定义父类
     2     pass
     3 
     4 class Water2: #定义父类
     5     pass
     6 
     7 class coke( Water1): #单继承,基类是ParentClass1,派生类是SubClass
     8     pass
     9 
    10 class feta(Water1,Water2): #python支持多继承,用逗号分隔开多个继承的类
    11     pass
      coke.__bases__ #__base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类
    (<class '__main__.coke'>,)
      feta.__bases__
    (<class '__main__.Water1'>, <class '__main__.Water2'>)

    经典类和新式类

    1.只有在python2中才分新式类和经典类,python3中统一都是新式类

    2.在python2中,没有显式的继承object类的类,以及该类的子类,都是经典类

    3.在python2中,显式地声明继承object的类,以及该类的子类,都是新式类

    3.在python3中,无论是否继承object,都默认继承object,即python3中所有类均为新式类

    提示:如果没有指定基类,python的类会默认继承object类,object是所有python类的基类,它提供了一些常见方法(如__str__)的实现。 他提供了双下方法

    经典类和新式类的区别
    1、关于基类 : 新式类默认继承object
    2、关于在子类中执行父类的方法:新式类有super,经典类只能用指名道姓
    3、关于多继承:新式类 广度优先(mro)经典类:深度优先
    在py3没有经典类;在py2里经典类和新式类共存
    
    关于继承:
    子类继承父类
    子类的对象调用方法,优先在子类中找,如果子类中有,就执行子类中的
                                    如果子类中没有,就执行父类的
                                        多个父类以广度优先为准
    
    关注self到底是哪个类的实例化

    派生

    子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类),一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。

    super()方法

    super代表的是父类 使用super比指名道姓的好处是 不用再后面的方法内传入self

     1 class A:
     2 
     3   def foo: print("A")
     4 
     5 class B(A):
     6 
     7   def foo(self) :
     8 
     9      super().foo            对象内部调用 super方法一
    10 
    11     super(B,self).foo       对象内部调用 super方法二                      
    12 
    13     print("B")
    14 
    15 b=B()
    16 super(B,b).foo         外部调用super方法      

    第四部分 组合

    #组合 —— 面向对象的一种功能
    #什么有什么的关系

    组合的本质是实例化一个对象,然后将对象作为另外一个对象的属性添加进去

     1 #组合例二:
     2 #人狗大战
     3 #
     4 #武器:伤害、属性
     5 class Weapon:
     6     def __init__(self,aggr,name,money):
     7         self.aggr = aggr
     8         self.name = name
     9         self.money = money
    10 
    11     def kill(self,dog_obj):
    12         print('%s武器暴击%s,伤害%s'%(self.name,dog_obj.name,self.aggr))
    13         dog_obj.life_value -= self.aggr
    14 
    15 class Dog:
    16     def __init__(self, name, type, aggr):
    17         self.name = name
    18         self.dog_type = type
    19         self.aggr = aggr
    20         self.life_value = 2000
    21 
    22     def bite(self, person_obj):  # self==egg,person_obj=alex
    23         # 属性的变化
    24         print('%s咬了%s' % (self.name, person_obj.name))
    25         person_obj.life_value -= self.aggr
    26 
    27 class Person:
    28     rol = ''  # 数据属性、静态属性、类属性
    29     country = '中国'
    30 
    31     def __init__(self, name, age, life_value):  # 初始化方法
    32         self.name = name  # 属性、对象属性
    33         self.theage = age
    34         self.life_value = life_value
    35         self.aggr = 1
    36 
    37     def attack(self, dog_obj):  # 函数属性、动态属性、方法
    38         print('%s攻击了%s' % (self.name, dog_obj.name))
    39         dog_obj.life_value -= self.aggr
    40 
    41 alex = Person('alex', 38, 500)
    42 egg = Dog('egon', '二哈', 20)
    43 alex.money = 2000
    44 knife = Weapon(200,'杀猪刀',1900)
    45 if alex.money > knife.money:
    46     alex.money -= knife.money
    47     alex.weapon = knife
    48 
    49 print(egg.life_value)
    50 alex.weapon.kill(egg)
    51 print(egg.life_value)
    View Code

    面向对象的进阶

    多态

    对象在接受数据的时候会忽略 数据类型

    封装

    封装就是把属性和方法 放入一个容器里装起来

    私有属性  私有方法

    class A:
      __NAME="xiaoming"               私有属性
      def foo(self):
        print(self.__name)
      
      def __foo2(self):             这个是私有方法
        print("2222")

    A.__NAME 是调不到的

    私有属性和私有方法无法直接在类外调用 但是类的内部可以调用 

    为什么私有方法无法在这调用呢?

    因为在本质是私有方法存在{'_A__NAME':'xiaoming'} __dict__中的key 不是__NAME而在类中调用__NAME的时候 自动给你转换成了_A__NAME

    如果你实在想在外部查看私有属性是可以的   _类名__名字

    a=A()
    a.foo()
    print(b._A__name,'zhoushuo')
    A._A__NAME 是可以调到的         #不合法

     私有属性和方法不能被继承

    静态属性的修改,和查看

    我们知道 我们有一种  _类名__属性名 的方式是可以查看和修改静态属性的 但这不是一种合规的操作.

    我理解的继承 是可以把父类的 属性名 和属性方法 实例化的时候 放入自己的__dict__内

    所以我们要从类的内部修改,和查看,这可以通过定义内部方法的方式实现

     1 class A:
     2     def __init__(self,name):
     3         self.__name=name
     4     @property
     5     def name(self):
     6         return self.__name
     7     @name.setter
     8     def name(self,new_name):
     9         self.__name=new_name
    10 a=A("alex")
    11 print(a.name)
    12 a.name="alex_sb"
    目的:希望属性不能从外部修改所以设置了私有属性
       又希望可以从外部能查看 所以设置同名的方法(函数)并使用
    @property.
    @property 装饰器的作用是把类的方法伪装成属性,调用的时候不用加()
    @方法名.setter 提供一种方法可以在设置方法的时候触发函数
    a.name="alex_sb"  这样我就可以通过给name赋值操作来从类的内部修改__name. 
    @name.setter 使用的时候需要 三红一致
    那这么做的意义是什么呢?
    我们知道 如果我们需要修改类的静态属性 仅仅需要.name="123" 就可以修改.
    那么这样我们有没有方法给这种修改增加更多的逻辑,通过
    @name.setter我们可以给修改添加跟多的逻辑.
    类中的装饰器

     issubclass(子类,父类)

    isinstance(对象,类名) 判断对象是不是这个类的实例化对象

    反射

    我认为反射的本质是根据字符串从名称空间中拿到对应名称的地址

    使用的是跟用对象取属性一样

    getattr(对象,属性名/方法) 

    hasattr(对象,属性名/方法)       hasattr() 函数用于判断对象是否包含对应的属性。

    setattr(对象,“对象属性名”,“对象属性值”) 可以给对象添加属性  方法

    delattr(对象,“方法属性名”,方法) 

    不过添加方法在调用的时候会报错 没有传入self

     双下方法

    __call__   对象加()后就会执行__call__方法

    __new__    构造方法    捏小人方法   

    创建对象   __new__方法需要return的是一个对象(当然这个对象,可以是任意的对象,不过通常是return父类__new__方法创建的对象.你也可以return一个其他对象,那么接下来执行__init__的时候就执行的是该对象的__init__方法)

    单例模式.单例模式是无论怎么实例化,实例化出来的对象都是一个.

    实现的原理就是

    class Singleton(object):
        _instance = None
        def __new__(cls, *args, **kw):
            if not cls._instance:
                cls._instance = super(Singleton, cls).__new__(cls, *args, **kw)  
            return cls._instance 
    object=super(Singleton, cls)   等于基类

    作用  依照Python官方文档的说法,__new__方法主要是当你继承一些不可变的class时(比如int, str, tuple), 提供给你一个自定义这些类的实例化过程的途径。还有就是实现自定义的metaclass。

    首先我们来看一下第一个功能,具体我们可以用int来作为一个例子:
    假如我们需要一个永远都是正数的整数类型,通过集成int,我们可能会写出这样的代码。
    
    
    class PositiveInteger(int):         我曹,还可以继承一个int类,继承整数类
        def __init__(self, value):
            super(PositiveInteger, self).__init__(self, abs(value))
    
    i = PositiveInteger(-3)
    print i
    
    class PositiveInteger(int):
        def __init__(self, value):
            super(PositiveInteger, self).__init__(self, abs(value))
     
    i = PositiveInteger(-3)
    print i
    但运行后会发现,结果根本不是我们想的那样,我们任然得到了-3。这是因为对于int这种 不可变的对象,我们只有重载它的__new__方法才能起到自定义的作用。
    这是修改后的代码:
    
    -------------------------------------------------------------------
    class PositiveInteger(int):
        def __new__(cls, value):
            return super(PositiveInteger, cls).__new__(cls, abs(value))
    
    i = PositiveInteger(-3)
    print i
    
    class PositiveInteger(int):
        def __new__(cls, value):
            return super(PositiveInteger, cls).__new__(cls, abs(value))
    i = PositiveInteger(-3)
    print i
    通过重载__new__方法,我们实现了需要的功能。 重构了对象
    

    __init__      初始化方法  穿衣服方法    给对象添加属性

    __str__  "%s"       %s 黏贴

    __reper__ "%r"    %r 会显示拼进来的东西真实的样子

    __len__           len()

    __hash__   

    __eq__        执行 == 的时候是执行eq方法

  • 相关阅读:
    【CF722E】Research Rover
    【CF1519E】Off by One
    【CF1519D】Maximum Sum of Products
    【CF702F】T-Shirts
    【CF1364E】X-OR
    RPA应用场景-自动轮询汇总报表
    RPA应用场景-财务报表统计整合
    RPA应用场景-公积金贷款业务数据整合和报送
    RPA应用场景-信用卡交易争议后续流程
    RPA应用场景-日终清算操作
  • 原文地址:https://www.cnblogs.com/surehunter/p/7781375.html
Copyright © 2011-2022 走看看