• python之面向对象


    一.初识面向对象

      1.类与对象的关系: 类是对事物的总结. 抽象的概念. 类用来描述对象. 对象是类的实例化的结果. 对象能执行哪些方法. 都由类来决定. 类中定义了什么. 对象就拥有什么

        class 类名:

          方法
        类()        #对象

    class Car:
        pass
    Car()
    
    •  注意:类名的首字母大写,严格遵守驼峰命名规范    

        1.1python中我们可以是用__init__(self)函数给对象进行初始化操作. 这个函数(方法)被称为构造函数(方法)或初始化方法

    •     在创建对象的时候会自动的调用 __init__()
    •     self是你创建出来的那个对象
    class Car: #创建类
        def __init__(self,color)
            self.color=color#属性
    c = Car() #创建对象
    

        1.2 方法 ->在类中的函数

    class Phone:  #创建类
        def __init__(self,color,price):  #初始化方法(构造方法)  自动调用
            self.color=color #属性
            self.price=price #属性
        def call(self,man):  #方法
            print(f'用我{self.color}手机给{man}打电话')
        def play(self):  #方法
            print('我%s的手机可以打游戏' % self.price)
    p = Phone('红色',5000)
    p.call('马云')
    p.play()

      2.面向对象和面向过程的对比    

        2.1⾯向过程: 一切以事物的流程为核心. 核心是"过程"二字, 过程是指解决问题的步骤,即, 先干什么, 后干什么.

    •     优点: 负责的问题流程化, 编写相对简单
    •     缺点: 可扩展性差

        2.2面向对象: 一切以对象为中心.

    •     优点: 可扩展性强
    •     缺点: 编程的复杂度高于⾯面向过程

      3.面向对象的三个特征

    •   ⾯向对象三大特征: 封装, 继承, 多态. 只要是面向对象编程语言. 都有这三个特征.

        3.1. 封装: 把很多数据封装到一个对象中. 把固定功能的代码封装到一个代码块, 函数, 对象, 打包成模块. 这都属于封装的思想.

        3.2. 继承: 子类可以自动拥有父类中除了私有属性外的其他所有内容. 在python中实现继承非常简单. 在声明类的时候, 在类名后面添加一个小括号,就可以完成继承关系. 那么什么情况可以使用继承呢?  两个类具有相同的功能或者特征的时候. 可以采用继承的形式. 提取一个父类, 这个父类中编写着两个类相同的部分. 然后两个类分别取继承这个类就可以了了.

    •   这样写的好处是我们可以避免写很多重复的功能和代码. 如果从语义中去分析的话. 会简单很多. 如果语境中出现了x是一种y. 这时, y是⼀一种泛化的概念. x比y更加具体. 那这时x就是y的子类.

        3.3. 多态: 同一个对象, 多种形态.

    •     多态的好处: 程序具有超⾼高的可扩展性. ⾯面向对象思想的核⼼心与灵魂.    

    二.类的成员

        什么是类的成员? 你能在类中写什么? 写的内容就是成员.

    class 类名:
        # 方法
        def __init__(self, 参数1, 参数2....):
        # 属性变量
            self.属性1 = 参数1
            self.属性2 = 参数2
            ....
        # 方法
        def method(self):
            pass            

      1.类的成员------变量

        1.1.实例变量,类变量(静态变量)

    •       实例变量是给对象用的,
    •      类变量对多个对象共享,最好用类名来访问
    class Person:
        country = "中国"  # 类变量, 表示所有的该类的对象都共享这个变量.
        def __init__(self, name, num, birthday):
            # 实例变量(字段) 表示你创建的每⼀个人都有这三个变量量
            self.name = name
            self.num = num
            self.birthday = birthday
    p1 = Person("alex", 18, "1840年年06⽉月01⽇日")
    print(p1.name) 
    print(p1.country) #中国
    p2 = Person("wusir", 28, "1894年年07⽉月25⽇日")
    print(p2.name) 
    print(p2.country)   #中国
      

      2.类的成员------方法

        2.1.实例方法(成员方法)  对象直接访问的方法叫实例方法

    class Computer:
        def play(self): #实例方法  参数为self
            print('电脑可以玩')
    c = Computer()
    c.play()   #对象直接调用实例方法

        2.2.类方法   @classmethod

        类方法需要在参数列表中的第一个位置预留一个位置, 通常我们给第一个参数起名字叫cls. 类方法在被调用的时候也不需要传递实例对象.但是. 系统会自动的把类传递给第一个参数. 类方法在编写的时候, 需要在类方法上面添加@classmethod

    class Phone:
    @classmethod
    def play(cls): #类方法 参数必须是cls
    print('我的手机可以打游戏')

        2.3.静态方法  @staticmethod

    •   静态方法不需要我们给方法传递self. 也就是说. 当出现一个方法不需要使用到成员变量的时候. 就可以选择使用静态方法. 静态方法需要我们在方法上面添加一个@staticmethod
    •   静态方法和静态变量一样. 一般都是使用类名直接访问和调⽤用的.
    class Phone:
        @staticmethod
        def func():  #静态方法   没有参数
            print('我的电话可以打电话')

      3.类的成员------属性  

        属性其实就是通过方法改造过来的一种变量的写法, 在方法上添加⼀个@property就可以了

    注意:
      1. ⽅法参数只能有⼀个self
      2. ⽅法上⽅要写@property
      3. 调用的时候, 我们不需要写括号. 直接当成属性变量来用就可以了.
      4. 这种套路只能取值. 不能设置值

    class Person:
        def __init__(self):
            pass
        @property
        def age(self):
            return 1
    p = Person()
    age = p.age
    print(age)        

      4.私有方法和私有变量

      在python中使用__作为⽅法或者变量的前缀. 那么这个方法或者变量就是一个私有的.

    class Person:
        def __init__(self, mimi):# 私有变量
            self.__mimi = mimi    
         def __age(self):#私有方法
            print("不告诉你")`

    三.类与类之间的关系

      1.依赖关系

    class Elphant:
        def __init__(self, name):
            self.name = name
        def open(self):
            '''
            开门
            :return:
            '''
            pass
        def close(self):
    
            '''
            关门
            :return:
            '''
            pass
    class Refrigerator:
        def open_door(self):
            print("冰箱门被打开了")
    def close_door(self):
        print("冰箱门被关上了")
    #大象和冰箱之间就是依赖关系. 我用着你. 但是你不属于我. 这种关系是最弱的.

      

      2.关联关系,组合关系,聚合关系

           其实这三个在代码上写法是一样的. 但是, 从含义上是不一样的.

    •     关联关系. 两种事物必须是互相关联的. 但是在某些特殊情况下是可以更改和更换的.

    •     聚合关系. 属于关联关系中的一种特例. 侧重点是xxx和xxx聚合成xxx. 各自有各自的声明周期. 比如电脑. 电脑⾥里里有CPU, 硬盘, 内存等等. 电脑挂了了. CPU还是好的. 还是完整的个体

    •     组合关系. 属于关联关系中的一种特例例. 写法上差不多. 组合关系比聚合还要紧密. 比如人的大脑, 心脏, 各个器官. 这些器官组合成一个人. 这时. 人如果挂了. 其他的东西也跟着挂了

      3.继承关系

        在面向对象的世界中存在着继承关系. 我们现实中也存在着这样的关系. 比如. x是一种y, 那x就可以继承y. 这是理解层面上的. 如果上升到代码层面. 我们可以这样认为. 子类在不影响父类的程序运行的基础上对父类进行的扩充和扩展. 这里.我们可以把父类被称为超类或者基类. 子类被称为派生类

    class Base:
        def __init__(self, num):
            self.num = num
        def func1(self):
            print(self.num)
    class Foo(Base):
        def func1(self):
            print("Foo. func1", self.num)
    obj = Foo(123)
    obj.func1()     # Foo. func1 123 运行的是Foo中的func1
    

      

    四.特殊成员

      1. 类名() 会自动执行__init__()
      2. 对象() 会自动执行__call__()
      3. 对象[key] 会自动执行__getitem__()
      4. 对象[key] = value 会自动执行__setitem__()
      5. del 对象[key] 会自动执行 __delitem__()
      6. 对象+对象 会自动执行 __add__()
      7. with 对象 as 变量 会自动执行__enter__ 和__exit__
      8. 打印对象的时候 会自动执行 __str__
      9. 干掉可哈希 __hash__ == None 对象就不可哈希了.

    • 创建对象的真正步骤:

        首先, 在执行类名()的时候. 系统会自动先执行__new__()来开辟内存. 此时新开辟出来的内存区域是空的. 紧随其后, 系统自动调用__init__()来完成对象的初始化工作. 按照时间轴来算.

        1. 加载类
        2. 开辟内存(__new__)
        3. 初始化(__init__)
          4. 使用对象干xxxxxxxxx

    五.反射

      1.isinstance  type和issubclass的应用

    •   issubclass() 这个内置函数可以帮我们判断xxx类是否是yyy类型的子类.
    class Base:
        pass
    class Foo(Base):
        pass
    class Bar(Foo):
        pass
    print(issubclass(Bar, Foo)) # True
    print(issubclass(Foo, Bar)) # False
    print(issubclass(Bar, Base)) # True
    
    •  type(obj) 表示查看obj是由哪个类创建的.

    class Foo:
        pass
    obj = Foo()
    print(obj, type(obj)) # 查看obj的类
    
    •   isinstance也可以判断xxx是yyy类型的数据.但是isinstance没有type那么精准.

    •        isinstance可以判断该对象是否是xxx家族体系中的(只能往上判断)

    class Base:
        pass
    class Foo(Base):
        pass
    class Bar(Foo):
        pass
    print(isinstance(Foo(), Foo)) # True
    print(isinstance(Foo(), Base)) # True
    print(isinstance(Foo(), Bar)) # False

      2.函数和方法的区分

    •   函数在打印的时候. 显示的是function. 而方法在打印的时候是method.
    class Foo:
        def chi(self):
            print("我是吃")
        @staticmethod
        def static_method():
            pass
        @classmethod
        def class_method(cls):
            pass
    f = Foo()
    print(f.chi) # <bound method Foo.chi of <__main__.Foo object at 0x10f688550>>
    print(Foo.chi) # <function Foo.chi at 0x10e24a488>
    print(Foo.static_method) # <function Foo.static_method at 0x10b5fe620>
    print(Foo.class_method) # bound method Foo.class_method of <class '__main__.Foo'>>
    print(f.static_method) # <function Foo.static_method at 0x10e1c0620>
    print(f.class_method) #<bound method Foo.class_method of <class '__main__.Foo'>>

      仔细观察, 我们能得到以下结论:

    •   1. 类方法. 不论任何情况, 都是方法.
    •   2. 静态方法, 不论任何情况. 都是函数
    •   3. 实例方法, 如果是实例访问. 就是方法. 如果是类名访问就是函数.

      3.反射

      关于反射, 其实一共有4个函数:

    •   1. hasattr(obj, str) 判断obj中是否包含str成员
    •   2. getattr(obj,str) 从obj中获取str成员
    •   3. setattr(obj, str, value) 把obj中的str成员设置成value. 注意. 这里的value可以是值, 也可以是函数或者方法
    •   4. delattr(obj, str) 把obj中的str成员删除掉

    六.约束,异常抛出,异常处理,MD5和日志的处理

    1.约束

    2.异常抛出

    3.日常处理

    4.MD5加密算法

    5.日志

    import logging
    
    # 配置好日志的处理, 默认就是GBK
    logging.basicConfig(filename='x1.txt', # 把日志信息写入的文件名
                        format='%(asctime)s - %(name)s - %(levelname)s -%(module)s: %(message)s',
                        datefmt='%Y-%m-%d %H:%M:%S', # 时间的格式
                        level=10) # 当前配置表示 10以上的分数会被写入日件
    
    # 向日志文件写入内容
    logging.critical("最高的") # 50, 几乎是最高的
    logging.error("最多的") # 40 平时使用最多的就是它
    logging.warn("警告") # 30  警告
    logging.warning("警告")
    logging.info("提示") # 20 级
    logging.debug("最低的") # 10
    logging.log(999, "自己定义一个等级")  #自己定义一个等级
    
    # 再创建⼀个操作⽇志的对象logger(依赖FileHandler)
    file_handler2 = logging.FileHandler('l2.log', 'a', encoding='utf-8')
    file_handler2.setFormatter(logging.Formatter(
        fmt="%(asctime)s - %(name)s -%(levelname)s -%(module)s: %(message)s"))
    logger2 = logging.Logger('百度贴吧', level=logging.DEBUG)
    logger2.addHandler(file_handler2)
    logger2.error("我才不去呢. 我们在北京. 离你那么远")
    import traceback
    class GenderException(Exception):
        pass
    class Person:
        def __init__(self, name, gender):
            self.name = name
            self.gender = gender
            logger1.info(f"这个人的名字是{self.name}, 这个人的性别是:{self.gender}")
    
        def xizao(self):
            print(f"{self.name}在洗澡")
    
    class ZaoTang:
    
        def nan(self, ren):
            if ren.gender == "男":
                ren.xizao()
            else:
                raise GenderException("我这里要的是男人")
    
        def nv(self, ren):
            if ren.gender == "女":
                ren.xizao()
            else:
                raise GenderException("我这里要的是女人")
    
    
    try:
        p1 = Person("赵亚磊", "男")
        p2 = Person("林志玲", "女")
        zaotang = ZaoTang()
        zaotang.nan(p2)
        zaotang.nv(p1)
    except GenderException:
        print("走错屋里了")
        logger1.error("走错屋了.. ")
        logger1.error(traceback.format_exc()) # 把堆栈信息记录在日志文件中

    七.MRO C3算法

      

      

      

  • 相关阅读:
    数组索引,内容交换
    查找两个等长升序线性表的中位数
    MarkDown使用小结
    java元注解
    LeetCode OJ:Valid Number
    LeetCode OJ:Insert Interval
    关于博客的格式
    9.Hive Metastore Administration
    3.控制hive map reduce个数
    6.capacity scheduler
  • 原文地址:https://www.cnblogs.com/l1222514/p/10169565.html
Copyright © 2020-2023  润新知