zoukankan      html  css  js  c++  java
  • python基础篇_006_面向对象

    面向对象

    1.初识类:

    # 定义一个函数,我们使用关键字 def 
    """
    def 函数名(参数):
        '''函数说明'''
        函数体
        return 返回值
    """
    
    
    def func():
        print("func execute...")
    # 定义一个类 使用关键字 class
    """
    class 类名:
        '''类说明'''
        类体
    """
    
    class C:
        pass
    class Person:
        role = 'person'  # 属性
    
        def walk(self):
            print("person is walking ... ")  # 动态属性

    2.类属性引用和实例化

    属性引用:类型.属性

    class Person:
        role = 'person'
    
        def walk(self):
            print("person is walking...")
    
    
    print(Person.role)  # 查看人的role属性
    print(Person.walk)  # 引用人的走路方法,注意,这里不是在调用,引用的是函数地址

    实例化:类名加括号就是实例化,会自动触发__init__函数的运行,可以用它来为每个实例定制自己的特征

    class Person:
        role = 'person'
    
        def __init__(self, name):
            self.name = name
    
        def walk(self):
            print("person is walking...")
    
    
    # 类实例化-->对象    对象 = 类名(参数)
    
    p1 = Person("zhangsan")  # Person("zhangsan") 调用__init__(self, name)方法,构造方法
    
    # 查看对象的属性 调用对象的方法
    print(p1.role)
    p1.walk()

    3.类命名空间与对象、实例的命名空间

    创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性
    
    而类有两种属性:静态属性和动态属性
    
    静态属性就是直接在类中定义的变量        类的数据属性是共享给所有对象的
    动态属性就是定义在类中的方法            类的动态属性是绑定到所有对象的
    
    创建一个对象/实例就会创建一个对象/实例的名称空间,存放对象/实例的名字,称为对象/实例的属性
    
    在obj.name会先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类...最后都找不到就抛出异常

    4.面向对象三大特性

    继承:

    新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类

    python中类的继承分为:单继承和多继承

    class ParentClass1:  # 定义父类
        pass
    
    
    class ParentClass2:  # 定义父类
        pass
    
    
    class SubClass1(ParentClass1):  # 单继承,基类是ParentClass1,派生类是SubClass
        pass
    
    
    class SubClass2(ParentClass1, ParentClass2):  # python支持多继承,用逗号分隔开多个继承的类
        pass

    先抽象在继承:

    增强代码重用性

    子类可以自己实现新的属性和方法,或者重新定义父类的,不会影响父类。

    在python3中,子类执行父类的方法也可以直接用super方法.

    抽象类与接口类

    继承有两种用途:
    
    一:继承基类的方法,并且做出自己的改变或者扩展(代码重用)  
    
    二:声明某个子类兼容于某基类,定义一个接口类Interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子类继承接口类,并且实现接口中的功能

    接口定义:

    from abc import ABCMeta, abstractmethod
    
    
    class Payment(metaclass=ABCMeta):
        @abstractmethod
        def pay(self, money):
            pass
    
    
    class Wechatpay(Payment):
        def pay(self, money):
            print("Wechatpay pay...")
    
        def fuqian(self, money):
            print('微信支付了%s元' % money)
    
    
    p = Wechatpay()  
    p.pay(100)
    依赖倒置原则:
    高层模块不应该依赖低层模块,二者都应该依赖其抽象;抽象不应该应该依赖细节;细节应该依赖抽象。换言之,要针对接口编程,而不是针对实现编程

    抽象类:
    只能被继承,不能实例化

    # 一切皆文件
    import abc  # 利用abc模块实现抽象类
    
    
    class All_file(metaclass=abc.ABCMeta):
        all_type = 'file'
    
        @abc.abstractmethod  # 定义抽象方法,无需实现功能
        def read(self):
            '子类必须定义读功能'
            pass
    
        @abc.abstractmethod  # 定义抽象方法,无需实现功能
        def write(self):
            '子类必须定义写功能'
            pass
    
    
    # class Txt(All_file):
    #     pass
    #
    # t1=Txt() #报错,子类没有定义抽象方法
    
    class Txt(All_file):  # 子类继承抽象类,但是必须定义read和write方法
        def read(self):
            print('文本数据的读取方法')
    
        def write(self):
            print('文本数据的读取方法')
    
    
    class Sata(All_file):  # 子类继承抽象类,但是必须定义read和write方法
        def read(self):
            print('硬盘数据的读取方法')
    
        def write(self):
            print('硬盘数据的读取方法')
    
    
    class Process(All_file):  # 子类继承抽象类,但是必须定义read和write方法
        def read(self):
            print('进程数据的读取方法')
    
        def write(self):
            print('进程数据的读取方法')
    
    
    wenbenwenjian = Txt()
    
    yingpanwenjian = Sata()
    
    jinchengwenjian = Process()
    
    # 这样大家都是被归一化了,也就是一切皆文件的思想
    wenbenwenjian.read()
    yingpanwenjian.write()
    jinchengwenjian.read()
    
    print(wenbenwenjian.all_type)
    print(yingpanwenjian.all_type)
    print(jinchengwenjian.all_type)

    抽象类与接口类:

    抽象类的本质还是类,指的是一组类的相似性,包括数据属性(如all_type)和函数属性(如read、write),而接口只强调函数属性的相似性。

    抽象类是一个介于类和接口直接的一个概念,同时具备类和接口的部分特性,可以用来实现归一化设计 

    多继承接口,接口定义一种规范

    多态:多态指的是一类事物有多种形态

    import abc
    
    
    class Animal(metaclass=abc.ABCMeta):
        @abc.abstractmethod
        def talk(self):
            pass
    
    
    class Person(Animal):
        def talk(self):
            print("person .. ")
    
    
    class Dog(Animal):
        def talk(self):
            print("Dog .. ")
    
    
    def talk(obj):
        obj.talk()
    
    talk(Person())

    封装:

     隐藏对象的属性和实现细节,仅对外提供公共访问方式

    【封装原则】
    
          1. 将不需要对外提供的内容都隐藏起来;
    
          2. 把属性都隐藏,提供公共方法对其访问。

    私有变量和私有方法:使用双下划线

    # 其实这仅仅这是一种变形操作
    # 类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式:
    
    class A:
        __N = 0  # 类的数据属性就应该是共享的,但是语法上是可以把类的数据属性设置成私有的如__N,会变形为_A__N
    
        def __init__(self):
            self.__X = 10  # 变形为self._A__X
    
        def __foo(self):  # 变形为_A__foo
            print('from A')
    
        def bar(self):
            self.__foo()  # 只有在类内部才可以通过__foo的形式访问到.
    
    # A._A__N是可以访问到的,即这种操作并不是严格意义上的限制外部访问,仅仅只是一种语法意义上的变形
    这种自动变形的特点:
    
    1.类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果。
    
    2.这种变形其实正是针对外部的变形,在外部是无法通过__x这个名字访问到的。
    
    3.在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。
    class A:
        __N = 0  # 类的数据属性就应该是共享的,但是语法上是可以把类的数据属性设置成私有的如__N,会变形为_A__N
    
        def __init__(self):
            self.__X = 10  # 变形为self._A__X
    
        def __foo(self):  # 变形为_A__foo
            print('from A')
    
        def bar(self):
            self.__foo()  # 只有在类内部才可以通过__foo的形式访问到.
    
    
    # A._A__N是可以访问到的,即这种操作并不是严格意义上的限制外部访问,仅仅只是一种语法意义上的变形
    a = A()
    # a.bar()
    
    print(a._A__N)  # 知道类名,属性名 就可以访问
    print(a._A__foo())

    私有方法:在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的

    5.property属性:

    一个静态属性property本质就是实现了get,set,delete三种方法

    class Goods:
    
        def __init__(self):
            # 原价
            self.original_price = 100
            # 折扣
            self.discount = 0.8
    
        @property
        def price(self):
            # 实际价格 = 原价 * 折扣
            new_price = self.original_price * self.discount
            return new_price
    
        @price.setter
        def price(self, value):
            self.original_price = value
    
        @price.deleter
        def price(self):
            del self.original_price
    
    
    obj = Goods()
    obj.price  # 获取商品价格
    obj.price = 200  # 修改商品原价
    print(obj.price)
    del obj.price  # 删除商品原价

    classmethod:

    class Classmethod_Demo():
        role = 'dog'
    
        @classmethod
        def func(cls):
            print(cls.role)
    
    
    Classmethod_Demo.func()

    staticmethod:

    class Staticmethod_Demo():
        role = 'dog'
    
        @staticmethod
        def func():
            print("当普通方法用")
    
    Staticmethod_Demo.func()

     6.isinstance和issubclass

    class A(object):
        pass
    
    
    a = A()
    
    # isinstance(obj,cls)检查是否obj是否是类 cls 的对象
    print(isinstance(a, object))
    # issubclass(sub, super)检查sub类是否是 super 类的派生类 
    print(issubclass(A, (object)))

    7.反射

    通过字符串的形式操作对象相关的属性 -- 自省

    hasattr  是否有该属性
    getattr  获取属性
    setattr  设置属性
    delattr  删除属性
    class Person():
        role = 'person'
    
        def __init__(self, name):
            self.name = name
    
        def walk(self):
            print("person is walking ...")
    
    
    p = Person("zhangsan")
    print(hasattr(p, 'name'))
    
    print(getattr(p, 'role'))
    
    print(setattr(p, 'name', 'lisi'))
    print(getattr(p, 'name'))
    
    print(delattr(p, 'role'))
    print(getattr(p, 'role'))  # AttributeError

    __str__和__repr__

    format_dict={
        'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型
        'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址
        'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名
    }
    class School:
        def __init__(self,name,addr,type):
            self.name=name
            self.addr=addr
            self.type=type
    
        def __repr__(self):
            return 'School(%s,%s)' %(self.name,self.addr)
        def __str__(self):
            return '(%s,%s)' %(self.name,self.addr)
    
        def __format__(self, format_spec):
            # if format_spec
            if not format_spec or format_spec not in format_dict:
                format_spec='nat'
            fmt=format_dict[format_spec]
            return fmt.format(obj=self)
    
    s1=School('oldboy1','北京','私立')
    
    print('from repr: ',repr(s1))
    print('from str: ',str(s1))
    print(s1)
    
    '''
    str函数或者print函数--->obj.__str__()
    repr或者交互式解释器--->obj.__repr__()
    如果__str__没有被定义,那么就会使用__repr__来代替输出
    注意:这俩方法的返回值必须是字符串,否则抛出异常
    '''
    print(format(s1,'nat'))
    print(format(s1,'tna'))
    print(format(s1,'tan'))
    print(format(s1,'asfdasdffd'))
  • 相关阅读:
    Java自定义注解(1)
    SpringMvc入门
    Nginx服务器简单配置
    EL和JSTL使用笔记
    JQuery笔记
    Java05 JDBC介绍及基本操作
    Java04 线程同步问题解决——线程锁(同步锁、互斥锁)
    web服务、正向代理、反向代理的一点理解
    java03 IO操作
    Docker05 Docker容器
  • 原文地址:https://www.cnblogs.com/yin-fei/p/10774759.html
Copyright © 2011-2022 走看看