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()

 

posted on 2017-08-16 16:51  黎明NB  阅读(217)  评论(0编辑  收藏  举报

导航