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

    1 # 2 == 3   # 值是否相等
    2 # 2 is 3   # 内存地址是否相等

    isinstance和issubclass

    isinstance(obj,cls)检查是否obj是否是类 cls 的对象 判断第一个参数是否是第二个参数的实例

    1 class A:pass
    2 class B(A):pass
    3 class C(B):pass
    4 c = C()
    5 print(isinstance(c,A))   # 包含继承关系的判断 #true

    issubclass(sub, super)检查sub类是否是 super 类的派生类 第一个参数是疑似子类,第二个参数是疑似父类.

    1 class A:pass
    2 class B(A):pass
    3 print(issubclass(A,B))  #false
    4 print(issubclass(B,A))  #true

    反射

    1 什么是反射

    反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。

    2 python面向对象中的反射:通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)

    四个可以实现自省的函数

    下列方法适用于类和对象(一切皆对象,类本身也是一个对象)

    1 # hasattr  判断某一个 变量 是否能够.调用一个名字,返回True或者False
    2 # getattr  直接获取一个变量中的名字的值
    3 
    4 class A:
    5     name = 'alex'   # 静态 属性
    6     age = 83        # 静态 属性
    7 print(getattr(A,'name')) #alex
    8 print(hasattr(A,'name')) #true
    hasattr,getattr
     1 class Student:
     2     def __init__(self,name,age):
     3         self.name = name
     4         self.age = age
     5     def show(self):
     6         for key in self.__dict__:
     7             print(key,self.__dict__[key])
     8 
     9 yuan = Student('苑昊',38)
    10 if hasattr(yuan,'name'):
    11     print(getattr(yuan,'name')) #苑昊
    12 if hasattr(yuan,'show'):
    13     func = getattr(yuan,'show')
    14     func()   #name 苑昊 age 38
    例子二
     1 # setattr  为一个变量增加或者修改一个属性
     2 # delattr  删除一个变量中的属性或者方法
     3 
     4 class Student:
     5     def __init__(self,name,age):
     6         self.name = name
     7         self.age = age
     8     def show(self):
     9         for key in self.__dict__:
    10             print(key,self.__dict__[key])
    11 
    12 hei = Student('小黑',18)
    13 hei.sex = '不详'
    14 print(hei.sex) #不详
    15 setattr(hei,'sex','不详')  # 增改操作
    16 print(hei.sex) #不详
    17 setattr(hei,'sex','male')
    18 print(hei.sex) #不详
    19 delattr(hei,'sex')    # 删除操作
    20 print(hei.__dict__)
    21 def wahaha(a,b):   # 专属于某一个对象的静态方法
    22     print(a,b) #{'name': '小黑', 'age': 18}
    setattr,delattr
     1 # 反射类中的名字
     2 # getattr(类名,'静态属性')
     3 # getattr(类名,'类方法')()
     4 # getattr(类名,'静态方法')()
     5 
     6 # 反射对象中的名字
     7 # getattr(对象名,'对象属性')
     8 # getattr(对象名,'方法名')()
     9 
    10 # 反射模块中的名字
    11 # import 模块名
    12 # getattr(模块名,'模块中的变量')
    13 # getattr(模块名,'模块中的函数')()
    14 # getattr(模块名,'模块中的类名')
    15 
    16 # 反射当前模块中的名字
    17 # import sys
    18 # getattr(sys.modules[__name__],'变量')
    19 # getattr(sys.modules[__name__],'函数')()
    20 # getattr(sys.modules[__name__],'类名')
    21 
    22 # sys.modules[__name__]
    23 # import sys
    24 # print(sys.modules[__name__])  # 所有导入过的模块
    25 # {'字符串数据类型的模块名':模块的内存地址}
    26 # {'__main__':当前模块的内存地址}
    View Code
    1 class  person:pass
    2 hei = person()
    3 setattr(hei,'name','小黑')
    4 setattr(hei,'age',18)
    5 print(hei,hei.__dict__)
    反射的知识
     1 # 怎么反射类 ?
     2 # class Student:
     3 #     def __init__(self,name,age):
     4 #         self.name = name
     5 #         self.age = age
     6 #     def show_student(self):
     7 #         for key in self.__dict__:
     8 #             print(key,self.__dict__[key])
     9 #
    10 # class Teacher:
    11 #     def __init__(self, name, age):
    12 #         self.name = name
    13 #         self.age = age
    14 #
    15 #     def show_teacher(self):
    16 #         for key in self.__dict__:
    17 #             print(key, self.__dict__[key])
    18 #
    19 # class Manager:
    20 #     def __init__(self, name, age):
    21 #         self.name = name
    22 #         self.age = age
    23 #
    24 #     def show_manager(self):
    25 #         for key in self.__dict__:
    26 #             print(key, self.__dict__[key])
    27 # hei = Student('小黑',18)
    28 # import sys
    29 # main = sys.modules[__name__]
    30 # import my_moudle
    31 # cls = getattr(my_moudle,'Student')
    32 # hei = cls('小黑',18)
    33 # print(hei,hei.__dict__)
    34 
    35 # 'Manager' 'Teacher' 'Student'
    36 # 获取字符串数据类型的类名
    37 # cls_name = input('>>>')
    38 
    39 # 根据输入反射找到具体的类
    40 # if hasattr(main,cls_name):
    41 #     cls = getattr(main,cls_name)
    42 
    43 # 实例化对象
    44 # alex = cls('alex',81)
    45 # print(type(alex))
    46 # 展示这个对象中的所有方法
    47 # for i in alex.__dict__:
    48 #     print(i,alex.__dict__[i])
    反射二

    __str__和__repr__

    改变对象的字符串显示__str__,__repr__

    自定制格式化字符串__format__

     1 #_*_coding:utf-8_*_
     2 
     3 format_dict={
     4     'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型
     5     'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址
     6     'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名
     7 }
     8 class School:
     9     def __init__(self,name,addr,type):
    10         self.name=name
    11         self.addr=addr
    12         self.type=type
    13 
    14     def __repr__(self):
    15         return 'School(%s,%s)' %(self.name,self.addr)
    16     def __str__(self):
    17         return '(%s,%s)' %(self.name,self.addr)
    18 
    19     def __format__(self, format_spec):
    20         # if format_spec
    21         if not format_spec or format_spec not in format_dict:
    22             format_spec='nat'
    23         fmt=format_dict[format_spec]
    24         return fmt.format(obj=self)
    25 
    26 s1=School('oldboy1','北京','私立')
    27 print('from repr: ',repr(s1))
    28 print('from str: ',str(s1))
    29 print(s1)
    30 
    31 '''
    32 str函数或者print函数--->obj.__str__()
    33 repr或者交互式解释器--->obj.__repr__()
    34 如果__str__没有被定义,那么就会使用__repr__来代替输出
    35 注意:这俩方法的返回值必须是字符串,否则抛出异常
    36 '''
    37 print(format(s1,'nat'))
    38 print(format(s1,'tna'))
    39 print(format(s1,'tan'))
    40 print(format(s1,'asfdasdffd'))
    View Code
     1 class B:
     2 
     3      def __str__(self):
     4          return 'str : class B'
     5 
     6      def __repr__(self):
     7          return 'repr : class B'
     8 
     9 
    10 b=B()
    11 print('%s'%b)
    12 print('%r'%b)
    %s和%r

    __del__

    析构方法,当对象在内存中被释放时,自动触发执行。

    注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

     1 import time
     2 class A:
     3     def __init__(self):
     4         self.f = open('userinfo','a')
     5     def consume(self):
     6         pass
     7     def __del__(self):
     8         '''在删除一个对象之前做一些收尾工作'''
     9         self.f.close()
    10         print('删除一个对象的时候调用我')
    11 
    12 a = A()
    13 time.sleep(1)
    14 del a
    15 # 删除一个对象的时候,如果内部存在__del__方法,
    16 # 那么在删除一个对象之前先执行__del__方法中的代码
    17 print(a) #  报错 name 'a' is not defined
    View Code

    item系列

    __getitem__\__setitem__\__delitem__

     1 class A:
     2     def __init__(self,name):
     3         self.name = name
     4         self.age = 81
     5     def __getitem__(self, item):
     6         return self.__dict__[item]
     7     def __setitem__(self, key, value):
     8         self.__dict__[key] = value
     9     def __delitem__(self, key):
    10         del self.__dict__[key]
    11 a = A('alex')
    12 print(a['name'])  # 对应了类中一个方法的语法 #alex
    13 a.name
    14 print(a['age'])  # 对应了类中一个方法的语法 #81
    15 a.age
    16 # 增加 和 修改一个属性
    17 a['sex'] = '不详'
    18 a.sex = '不详'
    19 print(a.__dict__)  #{'name': 'alex', 'age': 81, 'sex': '不详'}
    20 print(a.sex)  #不详
    21 print(a['sex']) #不详
    22 a['sex'] = ''
    23 print(a.__dict__) #'{'name': 'alex', 'age': 81, 'sex': '女'}
    24 del a['sex']
    25 print(a.__dict__) #'name': 'alex', 'age': 81}
    View Code

    __new__

     1 # 元类
     2 # 有一个元类 在创建类
     3 # type()  所有直接用class创建出来的类的元类都是type
     4 
     5 # class 类名(B,classMeta = 元类名)
     6 # class 类名(B,classMeta = type)  # 默认
     7 
     8 # 元类 创造 类     所以所有的类的type都是它的元类,默认是type
     9 # 类   创造 对象   具体创造对象的方法 __new__方法,所有的对象的type都是它对应的类
    10 
    11 # python中 一切皆对象
    12 # 变量 都有它属于的数据类型
     1 class A:
     2     def __init__(self):
     3         print('执行init方法了')
     4     def __new__(cls):
     5         print('执行new方法了')
     6         return object.__new__(cls)   # 创造对象,将对象返回
     7 
     8 a = A()
     9 print(type(a))
    10 # 执行new方法了
    11 # 执行init方法了
    12 # <class '__main__.A'>
    13 print(type(A))
    14 # 执行new方法了
    15 # 执行init方法了
    16 # <class 'type'>
    17 
    18 # 先执行__new__方法 创造出一个对象
    19 # 然后把创造出来的对象传递给__init__方法
    20 # 会把self自动的返回,被a接收
    View Code
     1 # 一个类 可以被多次实例化 但是同一时间在python的内存中,只能有一个实例
     2 class A:
     3     _instance = None
     4     def __init__(self,name):
     5         '''给娃穿衣服'''
     6         self.name = name
     7     def __new__(cls, *args, **kwargs):
     8         '''生娃的过程'''
     9         if not A._instance:
    10             A._instance = object.__new__(cls)
    11         return A._instance
    12 a1 = A('alex')  # 第一次实例化的时候创造一个实例
    13 print(a1.name)
    14 a2 = A('egon')
    15 print(a1.name,a2.name)  # 'alex' 'alex'
    单例模式

    __call__

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

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

    1 class A:
    2     def __call__(self,a):
    3         print('执行我了',a)
    4     def call(self,a):
    5         print('执行我了',a)
    6 a = A()
    7 a('abc')   # __call__   #执行我了 abc
    8 a.call('aaa') #执行我了 aaa
    View Code

    __len__

    1 def len(obj):
    2     return obj.__len__()
    3 print(len(hei))  #4
    View Code

    __eq__

     1 class A:
     2     def __init__(self,name,cls,age,sex):
     3         self.name = name
     4         self.cls = cls
     5         self.age = age
     6         self.sex = sex
     7     def __eq__(self, other):
     8         # if self.__dict__ == other.__dict__:return True
     9         return True
    10     def __len__(self):
    11         return len(self.__dict__)
    12 
    13 hei = A('小黑','py10期',18,'')
    14 hei2 = A('小2黑','py11期',17,'')
    15 print(hei.__dict__) #{'name': '小黑', 'cls': 'py10期', 'age': 18, 'sex': '无'}
    16 print(hei2.__dict__) #'name': '小2黑', 'cls': 'py11期', 'age': 17, 'sex': '无'}
    17 print(hei == hei2)  #True
    18 # 两个对象就算值是完全相等的,但是仍然内存地址不同
    19 # == 实际上是比较内存地址的
    20 # == 实际上是调用了__eq__方法
    View Code

    __hash__

    # hash(obj)函数,obj对象对应的类必然内部实现了__hash__方法
    # hash的结果就是__hash__方法的返回值
    # 且在一次成的执行过程中是不会发生变化的
    # 且要想作为字典的key或者作为集合的元素,这个对象对应的类必须实现__hash__方法
    1 # 不可变的数据类型都可以被hash
    2 class A:pass
    3     # def __hash__(self):
    4     #     return 1
    5 a = A()
    6 b = A()
    7 
    8 print(hash(a))   # object.__hash__()
    9 print(hash(b))   # object.__hash__()
    View Code

    __format__

     1 #_*_coding:utf-8_*_
     2 
     3 format_dict={
     4     'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型
     5     'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址
     6     'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名
     7 }
     8 class School:
     9     def __init__(self,name,addr,type):
    10         self.name=name
    11         self.addr=addr
    12         self.type=type
    13 
    14     def __format__(self, format_spec):
    15         return format_spec.format(obj=self)
    16 
    17 s1=School('oldboy1','北京','私立')
    18 print(format(s1,format_dict['tna'])) #私立:oldboy1:北京
    19 print(format(s1,format_dict['nat'])) #oldboy1-北京-私立
    20 print(format(s1,format_dict['tan'])) #私立/北京/oldboy1
    21 print(format(s1,'tna')) #tna
    22 print(format(s1,'tan')) #tan
    View Code

    面试题

     1 # 有一个类,对应这个类产生了100个对象
     2 # 每个对象有三个属性 : 姓名 年龄 性别
     3 # 请对这一百个对象进行去重,如果姓名和性别相同,即便年龄不同也是相同的对象
     4 # 问最简便的方法?
     5 class Person:
     6     def __init__(self,name,age,sex):
     7         self.name = name
     8         self.age = age
     9         self.sex = sex
    10     def __hash__(self):
    11         return hash('%s%s'%(self.name,self.sex))
    12     def __eq__(self, other):
    13         if self.name == other.name and  
    14             self.sex == other.sex:
    15             return True
    16 
    17 p_lst = []
    18 for i in range(100):
    19     p_lst.append(Person('egon',i,'male'))
    20 p_lst.append(Person('alex',i,'male'))
    21 p_lst.append(Person('yuan',i,'male'))
    22 print(p_lst)
    23 print(set(p_lst)) # 报错不可hash 完成了__hash__
    24 '''
    25 # hash是否相等   __hash__
    26 # 值是否相等     __eq__
    27 
    28 # 收获1
    29 # 对于一些python当中已经存在的内置函数 内置数据类型 内置模块中的方法
    30 # 都有可能依赖于类中的内置方法
    31 # 收获2
    32 # set方法依赖集合中元素对象的__hash__ __eq__
    33 '''
    金融公司
     1 from collections import namedtuple
     2 card = namedtuple('card',['num','col'])
     3 class A:
     4     num = [str(n) for n in range(2,11) ]+ list('jqka')
     5     col = ['红心','方板','梅花','黑桃']
     6     def __init__(self):
     7         self._cards = [card(num,col) for num in A.num
     8                       for col in A.col]
     9     def __len__(self):
    10         return  len(self._cards)
    11     def __getitem__(self, item):
    12         return self._cards[item]
    13     def __setitem__(self, key, value):
    14         self._cards[key] = value
    15 deck = A()
    16 print('**', deck[:]) #打印所有的纸牌
    17 from random import choice
    18 print(choice(deck)) #打印随机的纸牌 
    19 # deck对象对应的类中的getitem方法和len方法
    纸牌实例
  • 相关阅读:
    HTML连载10-details标签&summary标签&marquee标签
    [刷题] 7-14 然后是几点
    [刷题] 7-18 出租车计价 (15 分)
    [刷题] PTA 7-20 简单计算器
    [刷题] PTA 7-22 用天平找小球
    [刷题] PTA 7-24 猜数字游戏
    [刷题] PTA 7-28 求整数的位数及各位数字之和
    [刷题] PTA 7-30 念数字
    [刷题] PTA 7-37 输出整数各位数字
    [刷题] PTA 7-35 猴子吃桃问题
  • 原文地址:https://www.cnblogs.com/xiaobin12126/p/9383167.html
Copyright © 2011-2022 走看看