Python学习笔记27:反射,类的内置方法
参考:https://www.cnblogs.com/Eva-J/articles/7293890.html
类
# class 类名(父类1,父类2): 类名首字母要大写,可以加括号和不加括号,加括号里面写父类,不写默认Object # 静态属性 = '' # 静态属性 类属性 # def __init__(self): # 初始化方法,初始化里面不能加函数 # self.name = 'alex' # 如果内部已经实例化了,外面就可以直接获取 # # def func(self): # 动态属性 方法 # print(self.age) # 对象 = 类名() 实例化 # 对象.方法名() # 对象.属性名 # 对象.name # 对象.age = 18 # 对象.func() #类名.func(对象) # 组合 :表达的是 什么有什么的关系 #***** # 一个类的属性 是另外一个类的对象 # class Teacher: # pass # class Course: # def __init__(self,name,price,period): # self.name = name # self.price = price # self.period = period # python = Course('python',19800,'6 months') # class Classes: # def __init__(self,name,course): # self.name = name # self.course = course Classes类的属性是course类的对象(python) # # self.course_name = 'python' # pys9 = Classes('python_s9',python) # print(pys9.course.name) # python.name = 'python全栈' # print(pys9.course.name) # 命名空间 : 类和对象分别存在不同的命名空间中,对象找不到类中的名字的时候可以在往父类中去找 # 面向对象的三大特性 : 继承 多态 封装 # 继承 :查看继承__base__,如果没有指定基类,python的类会默认继承object类,object是所有python类的基类 # 单继承 : **** # 父类(超类、基类) # 子类(派生类):派生方法和派生属性 # 子类的对象在调用方法和属性 : 先用自己的 自己没有 才用父类的 # 多继承 :(面试) # 不会超过三个父类,不要超过三层 *** # 如果子类自己有用自己的,如果没有就用离子类最近的那个父类的方法 # 抽象类和接口类 ** # 经典类和新式类 继承规则不同 深度优先和广度优先 ***** (面试)需要记住钻石模型 # super 只能在python3中使用 mro **** #super是根据mro广度优先顺序找上一个类
# 多态 : (面试)多态指的是一类事物有多种形态
# 多态和鸭子类型
向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为(即方法)
# import abc
# class Animal(metaclass=abc.ABCMeta): #同一类事物:动物
# @abc.abstractmethod
# def talk(self):
# pass
#
# class People(Animal): #动物的形态之一:人
# def talk(self):
# print('say hello')
#
# class Dog(Animal): #动物的形态之二:狗
# def talk(self):
# print('say wangwang')
#
# class Pig(Animal): #动物的形态之三:猪
# def talk(self):
# print('say aoao')
# peo=People()
# dog=Dog()
# pig=Pig()
#peo、dog、pig都是动物,只要是动物肯定有talk方法
#于是我们可以不用考虑它们三者的具体是什么类型,而直接使用
# peo.talk()
# dog.talk()
# pig.talk()
#更进一步,我们可以定义一个统一的接口来使用
# def func(obj):
# obj.talk()
# 鸭子类型,Python崇尚鸭子类型,即‘如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子’
# python程序员通常根据这种行为来编写程序。例如,如果想编写现有对象的自定义版本,可以继承该对象
# 也可以创建一个外观和行为像,但与它无任何关系的全新对象,后者通常用于保存程序组件的松耦合度
#二者都像鸭子,二者看起来都像文件,因而就可以当文件一样去用
# class TxtFile:
# def read(self):
# pass
#
# def write(self):
# pass
#
# class DiskFile:
# def read(self):
# pass
# def write(self):
# pass
# 封装 : *** (面试)
# 私有的
# __名字
# 只能在类的内部调用 子类都无法继承
# 在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x
# 三个装饰器
# @property **** 规范 面试 #@name.setter
# @staticmethod ***
# @classmethod ***** 当一个方法只使用了类的静态变量时 就给这个方法加上@classmethod装饰器,默认传cls参数
反射
# 反射 : 是用字符串类型的名字 去操作 变量 # name = 1 # eval('print(name)') # 安全隐患 # 反射 就没有安全问题 # 反射 : 是用字符串类型的名字 去操作 变量 # 反射对象中的属性和方法 # hasattr getattr setattr delattr # class A: # def func(self): # print('in func') # # a = A() # a.name = 'alex' # a.age = 63 # # 反射对象的属性 # ret = getattr(a,'name') # 通过变量名的字符串形式取到的值 # print(ret) # print(a.__dict__) # 变量名 = input('>>>') # func # print(getattr(a,变量名)) # print(a.__dict__[变量名]) # # # 反射对象的方法 # a.func() # ret = getattr(a,'func') # ret() # # class A: # price = 20 # @classmethod # def func(cls): # print('in func') # # 反射类的属性 # # A.price # print(getattr(A,'price')) # # # 反射类的方法 :classmethod staticmethod # # A.func() # if hasattr(A,'func'): # getattr(A,'func')() #模块 # import my # 反射模块的属性 # print(my.day) # print(getattr(my,'day')) # 反射模块的方法 # getattr(my,'wahaha')() # 内置模块也能用 # time # asctime # import time # print(getattr(time,'time')()) # print(getattr(time,'asctime')())
# def qqxing():
# print('qqxing')
# year = 2018
# import sys
# # print(sys.modules['__main__'].year)
# # 反射自己模块中的变量
# # print(getattr(sys.modules['__main__'],'year'))
#
# # 反射自己模块中的函数
# # getattr(sys.modules['__main__'],'qqxing')() # 查看所有导入进来的模块,sys.modules['__main__']
# 变量名 = input('>>>')
# print(getattr(sys.modules[__name__],变量名))
# 要反射的函数有参数怎么办?
# print(time.strftime('%Y-%m-%d %H:%M:S'))
# print(getattr(time,'strftime')('%Y-%m-%d %H:%M:S'))
# 一个模块中的类能不能反射得到
# import my
# print(getattr(my,'C')())
# if hasattr(my,'name'):
# getattr(my,'name')
# setattr 设置修改变量
# class A:
# pass
# a = A()
# setattr(a,'name','nezha')
# setattr(A,'name','alex')
# print(A.name)
# print(a.name)
#
# # delattr 删除一个变量
# delattr(a,'name')
# print(a.name)
# delattr(A,'name')
# print(a.name)
内置方法
# 内置的类方法 和 内置的函数之间有着千丝万缕的联系 # 双下方法 # obj.__str__ str(obj) # obj.__repr__ repr(obj) # class Teacher: # def __init__(self,name,salary): # self.name = name # self.salary = salary # def __str__(self): # return "Teacher's object :%s"%self.name # def __repr__(self): # return str(self.__dict__) # def func(self): # return 'wahaha' # nezha = Teacher('哪吒',250) # print(nezha) # 打印一个对象的时候,就是调用a.__str__ # print(repr(nezha)) # print('>>> %r'%nezha) #a.__str__ --> object # object 里有一个__str__,一旦被调用,就返回调用这个方法的对象的内存地址 # l = [1,2,3,4,5] # 实例化 实例化了一个列表类的对象 # print(l) # %s str() 直接打印 实际上都是走的__str__ # %r repr() 实际上都是走的__repr__ # repr 是str的备胎,但str不能做repr的备胎 # print(obj)/'%s'%obj/str(obj)的时候,实际上是内部调用了obj.__str__方法,如果str方法有,那么他返回的必定是一个字符串 # 如果没有__str__方法,会先找本类中的__repr__方法,再没有再找父类中的__str__。 # repr(),只会找__repr__,如果没有找父类的 # 内置的方法有很多 # 不一定全都在object中 # class Classes: # def __init__(self,name): # self.name = name # self.student = [] # def __len__(self): # return len(self.student) # def __str__(self): # return 'classes' # py_s9= Classes('python全栈9期') # py_s9.student.append('二哥') # py_s9.student.append('泰哥') # print(len(py_s9)) # print(py_s9) #__del__ # class A: # def __del__(self): # 析构函数: 在删除一个对象之前进行一些收尾工作 # self.f.close() # a = A() # a.f = open() # 打开文件 第一 在操作系统中打开了一个文件 拿到了文件操作符存在了内存中 # del a # a.f 拿到了文件操作符消失在了内存中 # del a # del 既执行了这个方法,又删除了变量 # 引用计数 # __call__ # class A: # def __init__(self,name): # self.name = name # def __call__(self): # ''' # 打印这个对象中的所有属性 # :return: # ''' # for k in self.__dict__: # print(k,self.__dict__[k]) # a = A('alex')() # step1 # __str__ # __repr_ # __len__ # str() # len() # repr() 保持原有格式 # print(repr(1)) # print(repr('1')) # 内置类方法,和内置函数之间有关系,每次调用len()函数,实际上调用的是__len__