zoukankan      html  css  js  c++  java
  • day26:静态方法,类方法和反射

    1,包内部不要去尝试应用使用相对导入,一定不会成功的,他不支持这个机制,包内导入时一定要用绝对导入

    2,复习接口类,抽象类,Python中没有接口类,有抽象类,抽象类是通过abc模块中的metaclass = ABCMeta 和@abstractmethod实现的

    3,接口类和抽象类本质是做代码规范用的,我希望在子类中实现和父类方法名完全一样的方法

    4,二者区别,在JAVA的角度看是有区别的,JAVA没有多继承,所以为了接口隔离原则,就设计了接口这个概念,支持多继承;JAVA本来就支持单继承,所以就有了抽象类。Python中既支持单继承,也支持多继承,所以对于接口类和抽象类的区别就不那么明显了。甚至在Python中根本没有接口类,但是Python的扩展模块中有一个模块确实实现了接口类的概念,所以不能说根本没有,只是内置模块中没有,没有内置接口类。

    5,多态和鸭子类型,多态---Python天生支持多态,给子类找个爸爸,传爸爸的参数,Python里面崇尚鸭子类型,不依赖父类的情况下,实现两个类中的同名方法。

    6,封装 ---私有的,在Python中只要__名字,就把这个名字私有化了,私有化之后,就不能从类的外部直接调用了,可以私有的有静态属性方法,对象的属性都可以私有化,这种私有化只是从代码级别做了变形,并没有真的约束,变形机制 _类名__方法。在类外用这个调用,在类的外部__名字调用。

    7,私有属性

    class Room:
        def __init__(self,name,length,width):
            self.name = name
            self.__length =length
            self.__width = width
        
        def area(self):
            return self.__length * self.__width
    
    jin = Room('jin',3,5)
    print(jin.area())
    jin.name = 'lisa'
    print(jin.name)

    8,get set 方法保护属性不被修改,私有属性的查看方法

    class Room:
        def __init__(self,name,length,width):
            self.__name = name
            self.__length =length
            self.__width = width
    
        def get_name(self):
            return self.__name
    
        # 对私有对象的保护
        def set_name(self,new_name):
            if type(new_name) is str and new_name.isdigit() == False:
                self.__name = new_name
            else:
                print('invalid name')
    
        def area(self):
            return self.__length * self.__width
    
    jin = Room('jin',3,5)
    jin.name = '2' # 不是私有的话,可以随便改,要想办法约束一下
    print(jin.name)
    
    jin.set_name('lisa')
    print(jin.get_name())
    # C++ 里面所有的属性都设置成私有的,

     9,父类的私有属性可以被子类调用吗?否

    class Foo:
        __key = '123'  _Foo__key
    
    class Son(Foo):
        print(Foo.__key) #_Son__key # 此句报错,由于不可以调用 
    # AttributeError: type object 'Foo' has no attribute '_Son__key

    10,总结:会用到私有概念的场景,隐藏起一个属性,不想让类的外部调用;我想保护这个属性,不想让属性随意被改变;我想保护这个属性不被子类继承

    11,之前老师欠着的三个内置函数:property,classmethod,staticmethod

    12,property,内置装饰器函数,只在面向对象中使用,但是作为一个property属性,函数后面不能传递任何参数

    from math import pi
    class Circle:
        def __init__(self,r):
            self.r = r
    
        @property
        def perimeter(self):
            return 2 *pi *self.r
    
        @property
        def area(self):
            return self.r**2*pi
    
    c1 = Circle(5)
    # print(c1.area()) # 面积不是动作,是一个属性才合理,如何伪装成一个属性呢?
    print(c1.area)
    print(c1.perimeter)
    # c1.area = 70  # 不支持赋值

    13,BMI指数,方法伪装的属性,不被允许修改,怎么办?

    class Person:
        def __init__(self,name,high,weight):
            self.name = name
            self.high = high
            self.weigh = weight
            # self.bmi = wight / (high **2)  # 这样写虽然可以,但是不规范,操作属性的方法我们都是会在方法里面来写,各司其职,才更合理
    
        @property
        def bmi(self):
            return self.weigh/self.high**2
    
    jin = Person('jin',1.75,70)
    # print(jin.bmi())
    print(jin.bmi)
    jin.name = 'tiger'
    # jin.bmi = '23'  # 不允许修改,怎么办?

    14,方法一,name.setter 和 name.deleter

    class Person:
        def __init__(self,name):
            self.__name = name
    
        @property
        def name(self):
            return self.__name + ' nb'
    
        @name.setter
        def name(self,new_name):  # 虽然是同名函数,但是不会覆盖
            self.__name = new_name
    
        @name.deleter
        def name(self):pass  # 里面不实现的话,是没有办法删除的def self.name
    
    tiger = Person('tiger')
    # print(tiger.name())  # tigernb,另外改成property之后就不可以这样覅用了
    print(tiger.name)
    
    tiger.name = 'all students' # 无法修改怎么办?再定义一个函数
    print(tiger.name)
    
    del tiger.name # 删除属性
    print(tiger.name) 
    
    # 注意三个函数的名字必须一样,并且一定要有一个@property方法,才可以有后面两个

    15,和类属性的结合

    class Goods:
        discount = 0.8
        def __init__(self,name,price):
            self.name = name
            self.__price = price # 私有价格,只有自己知道
    
        @property
        def price(self):
            return self.__price * Goods.discount
    
    apple = Goods('apple',5)
    print(apple.price)

    16,staticmethod 静态的方法 三颗星,classmethod 类方法 四颗星,property 四星半,重要程度,私有属性,五颗星

    17,classmethod ,把一个方法 变成一个类中的方法,这个方法就可以直接被类调用,不被需要依托于任何对象

    class Goods:
        __discount = 0.8
        def __init__(self,name,price):
            self.name = name
            self.__price = price
    
        @property
        def price(self):
            return self.__price * Goods.__discount
    
        @classmethod
        def change_discount(cls,new_discount): # 去掉self,我们不推荐这样写,标准写法,不要写成其他的
            cls.__discount = new_discount
    
    
    # apple = Goods('apple',5)
    # print(apple.price)
    
    # 这个折扣修改的动作,我们如何不自己来完成,而是用一个函数来完成?
    # 如果我们定义成一个对象函数,那么我必须拿一个对象来进行折扣的修改,但是这个折扣是类属性,我希望所有的对象都自动修改
    # 而不是通过某一个
    # apple.change_discount(0.7)
    Goods.change_discount(0.9)
    # 当这个方法的操作只涉及静态属性的时候,就应该使用classmethod

    18,staticmethod,如果一个函数本身和类和对象都没有什么关系,但是我就想把这个函数写入到类里面,想象春面向对象的语言,例如JAVA,C#

    class Login:
        def __init__(self,name,password):
            self.name = name
            self.pwd = password
    
        def login(self):pass
    
        @staticmethod  # 不需要和类和对象产生任何关系,但是还可以放在类里面
        def get_usr_pwd():  # 必须把它扔进类里面,才是面向对象
            input('input usrname:')
            input('input password:')
    
    
    l  = Login('alex','3714')
    l.get_usr_pwd() # 静态方法既可以被对象来访问,也可以用类来访问
    Login.get_usr_pwd()
    
    # 何时使用静态方法
    # 在完全面向对象的程序中,如果一个函数,既和对象没有关系,也和类没有关系,那么就用staticmethod将这个函数编程一个静态方法
    
    # 类方法和静态方法都是类来调用的,那么对象可以调用吗?
    # 可以的,想象对象可以调用静态属性吗?一样的道理,但是一般情况下,推荐用类名来调用
    # 类方法,有一个默认参数 cls 代表这个类
    # 静态方法,没有默认参数,就像函数一样

    19,反射,非常重要,五颗星,把字符串当变量使用

    # name = 'lisa'
    # 'name'
    
    class Teacher:
        dic = {'show stu info','show teacher info'}
    
        def show_student(self):
            print('show student')
    
        def show_teacher(self):
            print('show teacher')
    
    # menu = Teacher.dic
    # for k in menu:
    #     print(k)
    
    'dic'
    
    # 最后三个内置函数
    # hasattr
    # getattr
    # defattr
    
    ret = getattr(Teacher,'dic')  # 左右对应 Teacher.dic
    print(ret)  # {'show stu info', 'show teacher info'}
    
    # python中一切皆是对象,包括类和模块

    20,反射类属性和类方法

    class Teacher:
        dic = {'show stu info','show teacher info'}
    
        def show_student(self):
            print('show student')
    
        def show_teacher(self):
            print('show teacher')
    
        @classmethod
        def func(cls):
            print('hahaha')
    
    
    ret = getattr(Teacher,'dic')  # 左右对应 Teacher.dic,类.属性
    print(ret)  # {'show stu info', 'show teacher info'}
    
    ret2 = getattr(Teacher,'func')
    ret2() # hahaha
    
    if hasattr(Teacher,'func2'):
        ret = getattr(Teacher,'func')
        ret()
    
    if hasattr(Teacher,'dic'):
        ret = getattr(Teacher,'dic')
        print(ret)

    21,反射对象方法

    # 反射对象函数
    lisa = Teacher()
    func = getattr(lisa,'show_student')
    func()

    22,使用实例,有了反射我就不用去一条条判断了,我只需要一条反射,去掉用相应的方法就行了,反射的妙用

    for k in Teacher.dic:
        print(k)
    
    key = input("输入需求:")
    # print(Teacher.dic[key])
    # 这个地方好在不需要去判断if key = 1 怎么样,key =2怎么样,用反射,程序自动就去调用了
    if hasattr(lisa,Teacher.dic[key]):
        func = getattr(lisa,Teacher.dic[key])
        func()

    23,反射非常的重要,也许现在只在面向对象这儿还体会不到他的好,但是到了以后网络编程,文件操作的时候,会用的非常多

    24,通过反射可以对象名获取对象属性和普通方法,类名获取静态属性和类方法和静态方法

    25,面向对象思维导图和计算器作业先欠着,后补

  • 相关阅读:
    JAVA_集合_作业01
    Java_Objects_hashCode
    Java成员内部类
    Java集合练习_实现购物车需求
    Java初级_单例设计模式
    HelloWorld
    vue中视频标点
    防抖节流?俩者区别?vue如何使用防抖、节流来解决点击问题?
    keep-alive
    axios和ajax的区别
  • 原文地址:https://www.cnblogs.com/lisa-blog/p/10247874.html
Copyright © 2011-2022 走看看