Python基础(四)

作者: EvanForEver | 来源:发表于2018-02-12 23:35 被阅读64次

    关于类与对象操作的BIFs

    1. type() 返回对象类型
    2. id(),查看对象id
    3. dir(),查看对象下变量及函数
    4. issubclass(),isinstance(), super(),类,实例,调父类
    5. hasattr(),getattr(),setattr(),delattr()类属性操作
    6. globals(),locals(),全局与局部的名称空间
    7. import(),reload(),模块的导入与重载

    面向对象编程OOP

    1.比较编程方式
     面向过程:根据业务逻辑从上到下写垒代码
     函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可,函数是对面向过程的一次封装
     面向对象:对函数进行分类和封装,让开发“更快更好更强…”,面向对象是更高一层的封装
    2.OOP的核心思想:
     类:从近似的对象中抽象出类
     对象:然后再从类出实例化出对象

    类的创建与实例化

    创建类

    1. class关键字
    2. 指定继承
    3. 定义类的成员
      数据成员
       类变量
       实例变量
      方法成员
       类方法
       实例方法

    实例化类

    class Student():
        #类变量
        student_total=0
        student_list=[]
        student_graduated=0
        pass_score=1000
        #魔法函数创建实例变量
        def __init__(self,name,age,gender):
            self.name=name
            self.age=age
            self.gender=gender
            self.__score=0
            Student.student_total+=1
            Student.student_list.append(name)
         #实例方法
        def exam(self,score):
            if score<60:
                return 'sorry, You have failed this time,better luck next time'
            else:
                self.__score+=score
                str1='Good!, Your score is now'+str(self.__score)
            
            if self.__score>=Student.pass_score:
                Student.student_graduated+=1
            return str1
        
        def check(self,):
            if self.score<Student.pass_score:
                return 'You have',Student.pass_score-self.score,' scores to archive!'
            else:
                return 'You have graduated from julyedu.com'
        #类方法
        @classmethod
        def get_student_graduated(cls,):
            return Student.student_graduated
        
        @classmethod
        def get_student_list(cls,):
            return Student.student_list    
        #普通方法
        @staticmethod
        def static1():
            return 'it can be called by both the instance and the class'
    
    xiaohong=Student('xiaohong',23,'female')
    
    xm=Student('xiaoming',22,'male')
    
    xm.exam(99)
    

    类的内部结构

    • 数据成员:[用于处理类及实例对象的相关数据]
       类变量:在类中且在函数体外,实例之间共享
       实例变量:定义在方法中,作用于当前实例的类
    • 方法成员(在类中定义的函数叫方法) :
       类方法:定义时需要使用@classmethod装饰器,第一个参数为cls。
       实例方法:绑定到实例的方法,第一个参数为self,只有实例能调用实例方法。
    • 静态方法[普通方法]
       定义的时候使用@staticmethod装饰器。
       静态方法没有参数限制,不需要实例参数self和类参数cls
       静态法可以通过类名访问,也可以通过实例访问。

    OOP三大特性总结

    • 继承
       创建一个类时可以从新开始,也可以从已经有的类继承下来,继承的类叫做subclass。
       super()用于子调用父类的方法
    #继承时在括号中加父类名字
    >>class list1(list):
    >>     name='this is list1 class'
    >>     #__name如果使用前双划,属性将被隐藏
    >>issubclass(list1,list) #判断list1是不是list的子类
    True
    
    >>class person():
    >>   def speak(self,):
    >>        return 'people can speak language!'
    >>    def work(self,):
    >>        print('people should have work to do!')
    
    >>class fireMan(person):
    >>    def work(self,):
    >>        print('A great work that can save people!')
    >>    def speak2(self,):
    >>        print(super().speak(),'FireMan needs to speak loudly!')
    
    >>fireman1=fireMan()
    >>fireman1.work()#多态,子类方法覆盖父类方法
    >>fireman1.speak2()#super方法调用父类
    A great work that can save people!
    people can speak language! FireMan needs to speak loudly!
    
    
    • 多态
       因为类具有继承关系,子类可以向上转型被看做是父类的类型,比如
      无论是战士还是快递员,都是人类。
       有了继承关系,子类可以继承父类的所有方法和属性,当然也可以重
      载父类的成员函数及属性。
       例如,当子类(直升机)和父类(飞机)都存在相同的fly()方法时,子
      类的fly()覆盖了父类的fly(),在运行时就总是会调用子类的fly()。
    • 封装
       封装就是将抽象的数据(变量)和行为(函数)打包,形成一个逻辑上的整体(即类);
       封装可以增强安全性(数据)并简化编程(函数),用户只能通过类对外接口的访问权限来使用类的成员。

    访问控制

    Python没有像其它语言有访问控制的关键字,例如private、protected等等。Python通过命名约定来实现的访问控制,例如在之前Student类的基础上,对其进行数据的保护。便其数据不能再被通过类名.或对象.的形式被调用。
     对模块级的控制,通过在标识符前加单下划线_实现。
     对类内部的属性及方法,通过在在标识符前加双下划线__来实现的私有化
     类中两个双下划线包裹的属性或方法为特殊

    魔法方法Magic Method

    • 魔术方法:
      魔法方法就是可以给你的类增加魔力的特殊方法,如果你的对象实现(重载)了这些方法中的某一个,那么这个方法就会在特殊的情况下被Python 所调用,你可以定义自己想要的行为,这些会自动发生
    • 当调用 x = SomeClass() 的时候, __init__ 并不是第一个被调用的方法。还有一个叫做__new__ 的方法,两个共同构成了“构造函数”。
      __new__是用来创建类并返回这个类的实例, 而__init__只是将传入的参数来初始化该实例。
      在对象生命周期调用结束时,__del__ 方法会被调用,可以将__del__理解为“构析函数”。
    • 它们经常是两个下划线包围来命名的

    案例

    #构造和初始化魔术
    >>class myclass():
    >>    def __init__(self,):
    >>        print('被__init__')
    
    >>    def __del__(self,):
    >>        print('我被__del__了,再见')        
    >>c1=myclass()
    被__init__
    >>del c1
    我被__del__了,再见
    
    比较魔术 作用
    __cmp__(self, other) 是最基本的用于比较的魔术方法。实现了所有的比较符号
    __eq__(self, other) 定义了等号的行为, == 。
    __ne__(self, other) 定义了不等号的行为, != 。
    __lt__(self, other) 定义了小于号的行为, < 。
    __gt__(self, other) 定义了大于等于号的行为, >= 。
    数值处理魔法
    __pos__(self) 实现正号的特性(比如 +some_object)
    __neg__(self) 实现负号的特性(比如 -some_object)
    __abs__(self) 实现内置 abs() 函数的特性。
    __invert__(self) 实现 ~ 符号的特性。
    __add__(self, other) 实现加法。
    __sub__(self, other) 实现减法。
    __mul__(self, other) 实现乘法。
    __floordiv__(self, other) 实现 // 符号实现的整数除法。
    __div__(self, other) 实现 / 符号实现的除法。
    __truediv__(self, other) 实现真除法。
    __iadd__(self, other) 实现赋值加法+=
    容器魔法
    __len__(self) 定义当被 len() 调用时的行为(返回容器中元素的个数)
    __getitem__(self, key) 定义获取容器中指定元素的行为,相当于 self[key]
    __setitem__(self, key, value) 定义设置容器中指定元素的行为,相当于 self[key] = value
    __delitem__(self, key) 定义删除容器中指定元素的行为,相当于 del self[key]
    __iter__(self) 定义当迭代容器中的元素的行为
    __reversed__(self) 定义当被 reversed() 调用时的行为
    __contains__(self, item) 定义当使用成员测试运算符(in 或 not in)时的行为
    反射 通过魔术方法控制使用 isinstance() 和 issubclass() 内置方法的反射行为。
    __instancecheck__(self, instance) 检查一个实例是不是你定义的类的实例
    __subclasscheck__(self, subclass) 检查一个类是不是你定义的类的子类
    调用
    __call__(self, [args...]) 允许一个类的实例像函数一样被调用,即x() 与 x.__call__() 是相同的. __call__ 参数可变。这意味着你可以定义 __call__ 为其他你想要的函数,无论有多少个参数

    案例

    #比较魔术
    class myclass():
        def __init__(self,num):
            self.num=num
            print('被__init__')  
            
        def __eq__(self,other):
            if type(other)==int:
                return True if self.num>other else False                
            else:
                print('can\'t compare with other datatype except int',)
    
    >>c1=myclass(3)
    被__init__
    >>c1=='china'
    cant compare with other datatype except int
    
    #数值处理魔法
    >>class myclass():
        def __init__(self,num):
            self.num=num
            print('被__init__')
            
        def __pos__(self):
            self.num=10086
    
    >>c1=myclass(-3)
    被__init__
    >>+c1
    >>c1.num
    10086
    
    #类表现魔法
    class myClass():
        __doc__='this is myClass docuemtnt'# 表示类的描述信息,重写代表自定义描述
        __name__='moduel name is V'#模块是对象,并且所有的模块都有一个内置属性 __name__。
    #一个模块的 __name__ 的值取决于如何应用模块。
    #如果 import 一个模块,那么模块__name__ 的值通常为模块文件名,不带路径或者文件扩展名。
    #但是也可以像一个标准的程序样直接运行模块.
    #在这种情况下, __name__ 的值将是一个特别缺省"__main__"。上述类中加上__name__ == '__main__'的判断语句
    #可以直接在终端环境下执行python dirfile.py /tmp进行测试,不必非得在交互式环境下导入模块进行测试。
    
    #容器魔法
    class FunctionalList():
    
        def __init__(self, values=None):#初始化
            if values is None:
                self.values = []
            else:
                self.values = values
    
        def __len__(self):
            return len(self.values)+10#故意多加10个
    
        def __getitem__(self, key):
            if type(key)==slice:#如果传入的key是一个slice类,则这是一个切片访问
                start=key.start
                stop=key.stop+1
                if key.stop==None:
                    stop=-1
                if key.start==None:
                    start=0
                return self.values[start:stop]
            else:
                return str(self.values[key])*2#故意多输出2次
        
    
        def __setitem__(self, key, value):
            self.values[key] = str(value)+'haha'#故意都给转成str,再加haha字样
    
        def __delitem__(self, key):
            pass
            #del self.values[key]#就是故意不去删
    
        def __iter__(self):
           #用于迭代器,之所以列表、字典、元组等可以进行for循环,是因为类型内部定义了 __iter__
           # pass
            return iter(self.values)
    
        def __reversed__(self):
            return reversed(self.values)
    
    
        def append(self, value):#非魔术方法
            self.values.append(value)
    
    >>l1=list(range(10))
    >>o1=FunctionalList(l1)
    >>len(o1)#调用的是__len__
    20
    >>o1[0:9]
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    #调用
    >>class callableInstance():
    
        def __init__(self, x, y):
            self.x, self.y = x, y
    
        def __call__(self,):
            self.x, self.y = self.y, self.x
            #调用时交换对象
        
    >>c1=callableInstance(1,5)# 执行 __init__,赋值x,y
    >>print(c1.x,c1.y)
    1 5
    >>c1()# 执行 __call__,交换变量变换
    >>print(c1.x,c1.y)
    5 1
    

    模块module

    1. 模块定义:一个.py文件,包含了对象定义与语句
    2. 模块作用:用来从逻辑上组织代码
    3. 模块使用:
    • 搜索路径(标准模块,自定义与第三方模块)路径(记得import sys)
       搜索路径设置(修改sys.path(sys.path.append()),设置环境变量)
    • 导入方法
       import test #作为模块空间导入
       from ** import * #指定模块下具体的类,对象导入,并入当前空间
       from *** import *** #将模块下所有对象导入,并入当前空间

    包package

    1. 包定义:
       含有init.py文件夹被称为包, init.py文件用于标识当前文件夹是一个包。
      (该文件可以为空,但必须有)
      包用于组织模块,通常把功能相近的模块进行再次封装成为包。
    2. 包的目录结构:
       模块
       子包
       (子包下的子包)
    3. 包的安装(pip,conda)
    4. 不同的导入方式(假设包名为test)
       import test#导入init.py这个moduel。
       from test import *#导入init.py这个moduel下所有对象导入到当前空间。
       from test.test_level1.test_level2 import test_level2#导入的层次目录下的模块。
      还是模块

    相关文章

      网友评论

        本文标题:Python基础(四)

        本文链接:https://www.haomeiwen.com/subject/myfxtftx.html