zoukankan      html  css  js  c++  java
  • python之面向对象进阶3

    1.isinstace和issubclass

    2.staticmethod和classmethod

    3.反射(hasattr、getattr、setattr.delattr等四个方法)

    4.内置方法

    5.logging

    6异常处理

    7hashlib摘要算法

    1.isinstace和issubclass 

    isinstace判断一个对象是否是一个类的对象。与type的区别;判断对象类型时一定要用type。

    class Foo:
        pass
    
    class Son(Foo):
        pass
    
    s = Son()
    #判断一个对象是不是这个类的对象,传两个参数(对象,类)
    print(isinstance(s,Son))
    print(isinstance(s,Foo))
    # print(type(s) is Son)
    # print(type(s) is Foo)

    issubclass判断一个类是不是另一个类的子类。

    class Foo:
        pass
    
    class Son(Foo):
        pass
    
    s = Son()
    
    
    #判断一个类是不是另一类的子类,传两个参数(子类,父类)
    # print(issubclass(Son,Foo))
    # print(issubclass(Son,object))
    # print(issubclass(Foo,object))
    # print(issubclass(int,object))

    2.@staticmethod 和@classmthod

    @staticmetho(静态方法)  没有默认参数让类里的方法直接被调用,就像正常函数一样。(可以被类和对象调用,不推荐用对象调)

    class Student:
        f = open('student', encoding='utf-8')
        def __init__(self):
            pass
    
        def func(self):
            pass
        @staticmethod   #静态方法  : 让类里的方法直接被类调用,就像正常的函数一样
        def show_student_info_static():
            f = open('student', encoding='utf-8')
            for line in f:
                name, sex = line.strip().split(',')
                print(name, sex)
    s=Student()
    s.show_student_info_static()
    print(Student.show_student_info_static)

    @classmethod(类方法)          默认参数是cls,可以直接使用类和对象调用,不推荐用对象调。

    class Student:
        f = open('student', encoding='utf-8')
        def __init__(self):
            pass
    
        def func(self):
            pass
    
        @classmethod   #类方法:默认参数cls,可以直接用类名调用,可以与类属性交互
        def show_student_info_class(cls):
            for line in cls.f:
                name, sex = line.strip().split(',')
                print(name, sex)    
    
    s=Student()
    s.show_student_info_class()
    print(Student.show_student_info_class)

    总结:

    #classmethod和staticmethod
    #相同:都可以直接被类调用,不需要实例化
    #不同:
    #类方法必须有一个cls参数表示这个类,可以使用类属性
    #静态方法不需要,静态方法不能直接使用
    
    #绑定方法
    #非绑定方法
    
    #普通方法  默认有一个self对象传进来,并且只能被对象调用——绑定到对象
    #类方法    默认有一个cls传进来表示本类,并且可以被类和对象(不推荐)调用——绑定到类
    #静态方法  没有默认参数,并且可以被类和对象(不推荐)调用——非绑定
    #classmethod和staticmethod
    #相同:都可以直接被类调用,不需要实例化
    #不同:
    #类方法必须有一个cls参数表示这个类,可以使用类属性
    #静态方法不需要,静态方法不能直接使用
    
    #绑定方法
    #非绑定方法
    
    #普通方法  默认有一个self对象传进来,并且只能被对象调用——绑定到对象
    #类方法    默认有一个cls传进来表示本类,并且可以被类和对象(不推荐)调用——绑定到类
    #静态方法  没有默认参数,并且可以被类和对象(不推荐)调用——非绑定

    3.反射(常用:hasattr、getattr;不常用:setattr、delattr)(通过字符串的形式来访问对象的属性与调用对象的方法)(应用范围为 对象、类、模块)

    hasattr与getattr:

    class Foo:
        def __init__(self):
            self.name = 'egon'
            self.age = 73
    
        def func(self):
            print(123)
    
    egg = Foo()
    print(hasattr(egg,'name'))#返回bool
    print(getattr(egg,'name'))
    if hasattr(egg,'func'):   #返回bool
        Foo_func = getattr(egg,'func')  #如果存在这个方法或者属性,就返回属性值或者方法的内存地址
                                     #如果不存在,报错,因此要配合hasattr使用
        Foo_func()#执行func方法

    不常用的setattr与delattr

    class Foo:
        def __init__(self):
            self.name = 'egon'
            self.age = 73
    
        def func(self):
            print(123)
    
    egg = Foo()
    
    def show_name(self):
        print(self.name + ' sb')
    setattr(egg,'sh_name',show_name)#新增一个方法
    # egg.sh_name(egg)#新增方法调用时要传参数就是对象自己
    # show_name(egg)#通过函数调用
    class Foo:
        def __init__(self):
            self.name = 'egon'
            self.age = 73
    
        def func(self):
            print(123)
    
    egg = Foo()
    # delattr
    delattr(egg,'name')
    print(egg.name)

    反射的延伸:(类也是对象)

    我们一般用hasattr判断是否有这个属性或方法,用getattr方法调用这个属性或者方法
    class Foo:
        f = 123 #类变量
        @classmethod#类方法
        def class_method_demo(cls):
            print('class_method_demo')
        @staticmethod#静态方法
        def static_method_demo():
            print('static_method_demo')
    if hasattr(Foo,'f'):#类属性
        print(getattr(Foo,'f'))
    print(hasattr(Foo,'class_method_demo'))
    method = getattr(Foo,'class_method_demo')
    method()
    print(hasattr(Foo,'static_method_demo'))
    method2 = getattr(Foo,'static_method_demo')
    method2()
    #类也是对象

    模块使用反射分为引入模块与本类模块

    引入模块:

    import my_module
    print(hasattr(my_module,'test'))
    # func_test = getattr(my_module,'test')
    # func_test()
    getattr(my_module,'test')()

    在本模块中的使用

    def demo1():
        print('喜欢你')
    
    import sys
    # print(__name__)  #'__main__'
    # print(sys.modules)
    #'__main__': <module '__main__' from 'D:/Python代码文件存放目录/S6/day26/6反射3.py'>
    module_obj =sys.modules[__name__]  #sys.modules['__main__']
    # module_obj : <module '__main__' from 'D:/Python代码文件存放目录/S6/day26/6反射3.py'>
    # print(module_obj)
    print(hasattr(module_obj,'demo1'))
    getattr(module_obj,'demo1')()
    #在本模块中应用反射                              

    4内置方法

    (str与repr)

    class Foo:
        def __init__(self,name):
            self.name = name
        # def __str__(self):
        #     return '%s obj info in str'%self.name
        def __repr__(self):
            return ' obj info in repr'# f = Foo('egon')
    # print(f)
    # print('%s'%f)
    # print('%r'%f)
    # print(repr(f))  # f.__repr__()
    # print(str(f))
    #当打印一个对象的时候,如果实现了str,打印返回值
    #当str没有被实现的时候,就会调用repr方法
    #但是当你用字符串格式化的时候 %s和%r会分别去调用__str__和__repr__
    #不管是在字符串格式化的时候还是在打印对象的时候,repr方法都可以作为str方法的替补
    #但反之不行
    #用于友好的表示对象。如果str和repr方法你只能实现一个:先实现repr

    del方法

    class Foo:
        def __del__(self):
            print('执行我啦')
    
    f = Foo()
    print(123)
    print(123)
    print('..........')
    print(123)
    print(123)
    print(123)

    __new__方法

    class A:
        def __init__(self):  #在执行__init__方法有一个方法在帮你创造self
            print('in init function')
            self.x = 1
    
        def __new__(cls, *args, **kwargs):#先执行__new__方法
            print('in new function')
            return object.__new__(A, *args, **kwargs)
    a = A()
    b = A()
    c = A()
    d = A()

    单例模式

    class Singleton:
        def __new__(cls, *args, **kw):
            if not hasattr(cls, '_instance'):
                cls._instance = object.__new__(cls, *args, **kw)
            return cls._instance
    
    one = Singleton()
    two = Singleton()
    print(one,two)
    one.name = 'alex'
    print(two.name)

    __call__方法

    对象后面加括号,触发执行。

    注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

    class Foo:
        def __call__(self, *args, **kwargs):
            print(123)
    
    Foo()()

    __len__

    class Foo:
        def __len__(self):
            return len(self.__dict__)
        def __hash__(self):
            print('my hash func')
            return hash(self.name)
    f = Foo()
    print(len(f))
    f.name = 'egon'
    print(len(f))
    print(hash(f))

    __hash__与__eq__   set方法依赖__hash__和__eq__这两个内置方法

    #留下同样名字和性别的对象
    class Person:
        def __init__(self,name,age,sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        def __hash__(self):
            return hash(self.name+self.sex)
    
        def __eq__(self, other):
            if self.name == other.name and self.sex == other.sex:
                return True
    
    p_lst = []
    for i in range(84):
        p_lst.append(Person('egon',i,'male'))
    print(p_lst)
    print(set(p_lst))

    纸牌游戏

    from collections import namedtuple
    Card = namedtuple('Card',['rank','suit'])  #每一个card的对象就是一张纸牌
    
    class FranchDeck:
        ranks = [str(n) for n in range(2,11)] + list('JQKA')
        suits = ['红心','方板','梅花','黑桃']
    
        def __init__(self):
            self._cards = [Card(rank,suit) for rank in FranchDeck.ranks
                                            for suit in FranchDeck.suits]
    
        def __len__(self):
            return len(self._cards)
    
        def __getitem__(self, item):
            return self._cards[item]
    
        def __setitem__(self, key, value):
            self._cards[key] = value
    
        def __call__(self, *args, **kwargs):
            return self._cards
    
    deck = FranchDeck()
    print(deck[0])
    print(deck[3])
    print(deck[2])
    print(deck[1])
    # from random import shuffle   #shuffle可以打乱顺序
    # shuffle(deck)#洗牌
    # print(deck())
    # shuffle(deck)
    # print(deck())#洗牌

    5 logging

    通过config来配置只能选择一种输出模式

    import logging
    #config只能写文件里或者打印在屏幕上2个选择一个
    # logging.basicConfig(
    #     level=logging.DEBUG,
    #     format = '%(name)s %(asctime)s [%(lineno)d] -- %(message)s',#需要输出的内容
    #     datefmt = '%d/%m/%y %H:%M:%S',#日期格式
    #     filename = 'logging_info'#如果出现它那就是要要把内容放在文件里不会打印到屏幕上
    # )
    # logging.debug("debug")
    # logging.info("info")
    # logging.warning("出错了")

    logger可以输出屏幕和写入文件

    # logger对象可以选择打印或者写在文件里
    import logging
    def my_logger(filename,file=True,stream = True):
        logger = logging.getLogger()
        formatter = logging.Formatter(fmt='%(name)s %(asctime)s [%(lineno)d] --  %(message)s',
                                      datefmt='%d/%m/%y %H:%M:%S')#指定打印的格式和数据
        logger.setLevel(logging.DEBUG)  #指定日志打印的等级
        if file:
            file_handler = logging.FileHandler(filename,encoding='utf-8')#格式
            file_handler.setFormatter(formatter)  # 文件流 文件操作符
            logger.addHandler(file_handler)
        if stream:
            stream_handler = logging.StreamHandler()
            stream_handler.setFormatter(formatter) #屏幕流 屏幕操作符
            logger.addHandler(stream_handler)
        return logger
    
    logger = my_logger('logging')
    logger.warning("出错了")
    logger.debug("debug")

    推荐使用logger

    6异常处理

    架构

    try:
        pass
    except ValueError:
        pass
    except Exception as e:
        print('统筹处理所有错误的措施')
    else:
        print("针对这段try中的代码没有异常要特别处理的")
    finally:
        print("不管有没有异常都要执行的代码")

    7hashlib摘要算法

    import hashlib
    md5_obj = hashlib.md5('nezha'.encode('utf-8'))#加盐啦
    md5_obj.update('123456'.encode('utf-8'))
    print(md5_obj.hexdigest())
    md5_obj.update('hello,egon~'.encode('utf-8'))
    print(md5_obj.hexdigest())

    主要用途:

    # 文件校验
    # 文件是否被改变
    # 登录密码
    # 不能解密,但可以“撞库”
    # 加盐 hashlib.md5('nezha'.encode('utf-8'))
    给文件加密
    import hashlib
    md5_obj = hashlib.md5()
    import os
    filesize = os.path.getsize('filename')#需要自己创建一个文件
    f = open('filename','rb')
    while filesize>0:
        if filesize > 1024:
            content = f.read(1024)
            filesize -= 1024
        else:
            content = f.read(filesize)
            filesize -= filesize
        md5_obj.update(content)
    # for line in f:#这是另一个加密的方式
    #     md5_obj.update(line.encode('utf-8'))#这两种不同的加密方式得到的结果是一样的
    md5_obj.hexdigest()
  • 相关阅读:
    【并发】基于 @Async和 CompletableFuture 实现并发异步操作
    【HTTP】使用 RestTemplete 实现 post请求
    【AICC】2019训练营笔记
    【Hadoop】CDH、Presto配置问题
    【Linux】文件拷贝-Linux当前目录所有文件移动到上一级目录(转)
    【Linux】linux ln文件夹的链接(转)
    【Hadoop】新建hadoop用户以及用户组,给予sudo权限(转)
    【Centos】桌面安装(转)
    【CentOS7】CentOS7各个版本镜像下载地址(转)
    【Spark】ScalaIDE运行spark,A master URL must be set in your configuration
  • 原文地址:https://www.cnblogs.com/1a2a/p/7373881.html
Copyright © 2011-2022 走看看