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方法
    纸牌实例
  • 相关阅读:
    VOA 2009/11/02 DEVELOPMENT REPORT In Kenya, a Better Life Through Mobile Money
    2009.11.26教育报道在美留学生数量创历史新高
    Java中如何实现Tree的数据结构算法
    The Python Tutorial
    VOA HEALTH REPORT Debate Over New Guidelines for Breast Cancer Screening
    VOA ECONOMICS REPORT Nearly Half of US Jobs Now Held by Women
    VOA ECONOMICS REPORT Junior Achievement Marks 90 Years of Business Education
    VOA 2009/11/07 IN THE NEWS A Second Term for Karzai; US Jobless Rate at 10.2%
    Ant入门
    Python 与系统管理
  • 原文地址:https://www.cnblogs.com/xiaobin12126/p/9383167.html
Copyright © 2011-2022 走看看