• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
KK筑梦人
博客园    首页    新随笔    联系   管理    订阅  订阅

面向对象的进阶->反射、面向对象的进阶->内置方法 第二十二天 2018.11.9

上节复习:

静态属性,类方法,普通方法(混淆)

class 类名(父类1,父类2):
    静态属性 = ''          # 静态属性 类属性
    def __init__(self):    # 初始化方法
        self.name = 'alex'

    def func(self):        # 动态属性 方法
        print(self.age)

对象 = 类名()  对象.方法名()  对象.属性名 可以通过对象.属性名=XXX,直接给对象属性重新赋值,或者给对象建立新属性和赋值               对象.func() #类名.func(对象)

组合 :表达的是 什么有什么的关系 #*****     一个类的属性 是另外一个类的对象

继承 : 表达的上 什么是什么的关系

class Course:
    def __init__(self,name,price,period):
        self.name = name
        self.price = price
        self.period = period        #周期
python = Course('python',19800,'6 months')    #建立Course的实例化对象
class Classes:
    def __init__(self,name,course):
        self.name = name
        self.course = course        #Classes类的属性是Course类的对象---->组合
        # self.course_name = 'python'   #只是给Classes类的对象加了一个属性---->属性名为Course_name 属性值为固定的python
pys9 = Classes('python_s9',python)    #建立Classes的实例化对象
print(pys9.course.name)           #对象名.属性名---->Classes属性名==Course对象名.属性名
python.name = 'python全栈'       #将Course对象的属性值重新赋值修改
print(pys9.course.name)           #找的Course对象的属性值也会跟着变化

命名空间:类和对象分别存在不同的命名空间中

面向对象的三大特性 : 继承 多态 封装

继承 :

  单继承 : ****

    父类(超类、基类)

    子类(派生类):派生方法和派生属性

    子类的对象在调用方法和属性 : 先用自己的 自己没有 才用父类的

  多继承 :(面试)

    不会超过三个父类,不要超过三层 ***

    如果子类自己有用自己的,如果没有就用离子类最近的那个父类的方法

    抽象类和接口类 **

    经典类和新式类 继承规则不同 深度优先和广度优先 ***** (面试)

  super 只能在python3中使用 mro ****

    super是根据mro广度优先顺序找上一个类

多态 : (面试)

  多态和鸭子类型

封装 : *** (面试)

  私有的

  __名字

  只能在类的内部调用 子类都无法继承

三个装饰器

  @property **** 规范 面试 #@name.setter

  @staticmethod ***

  @classmethod ***** 当一个方法只使用了类的静态变量时 就给这个方法加上@classmethod装饰器,默认传cls参数

class Goods:
    __discount = 0.8       #私有类属性       折扣率
    def __init__(self,name,price):
        self.name=name
        self.__price=price    #定义为私有属性
    @classmethod         #下面最接近的方法变成类方法,可以直接被类调用,不需要依赖任何对象
    def change_discount(cls):       #类方法形参必须为cls,后面可以和self一样,加形参
        cls.__discount = 0.5        #修改掉discount,私有属性在本类中可以被随便使用
    @property                       #把原价定义为私有,用装饰器把price方法定义为公有方法 通过在类外调用同名方法进而使用
    def price(self):     #不可以传入cls,cls传入的只不过是一个类似'name','age'一样的属性,并不是cls对象的类属性
        return self.__price*self.__discount   #不可以表示为cls.__discount,类方法里面找不到cls对象
Goods.change_discount()
PG=Goods('苹果',5)
print(PG.price)           #对象名.方法,调用的是方法,price方法中无self.__price重新赋值,因此不可以用对象名.方法(实参)

判断类与对象关系的两个方法:

isinstance(对象名a,类名B)检      对象a是否是类B的对象---->True是---->False不是

issubclass(类B, 类A)检查类B是否是类A的派生类---->True是---->False不是

class A:pass
class B(A):pass
a = A()
print(isinstance(a,A))   #True
print(issubclass(B,A))   #True
print(issubclass(A,B))   #False

面向对象的进阶---->反射

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

反射 : 是用字符串类型的名字 去操作 变量(反射 就没有安全问题)

name = 1
eval('print(name)')  # 安全隐患
eval---->提取并且执行

反射对象中的属性和方法  hasattr getattr setattr delattr

getattr:通过变量名的字符串形式取到的值

反射对象的属性和对象的方法getattr(对象名,'变量名/方法名')获得的方法是该方法的内存地址,执行在后面加()即可

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

反射类的属性和类的方法:getattr(类名,'属性名/方法名')获得的类方法是类方法的内存地址,执行在后面加()即可

类方法一般只有:classmethod staticmethod   对象.方法---->调用的是普通方法

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

反射模块的属性和模块的方法getattr(模块名,'方法名')获得的方法是方法的内存地址,执行在后面加()即可

#模块
import my
#反射模块的属性
print(my.day)
print(getattr(my,'day'))

#反射模块的方法
getattr(my,'wahaha')()

#内置模块也能用
#time
#asctime
import time
print(getattr(time,'time')())
print(getattr(time,'asctime')())

反射自己模块中的变量和函数和类 getattr(sys.modules[__name__],'变量名/函数名/类名')  

def qqxing():
    print('qqxing')
year = 2018
import sys
print(sys.modules['__main__'].year)      #sys.modules获得当前模块的所有导入模块---->字典格式
#反射自己模块中的变量
print(getattr(sys.modules['__main__'],'year'))

#反射自己模块中的函数
getattr(sys.modules['__main__'],'qqxing')()
变量名 = input('>>>')
print(getattr(sys.modules[__name__],变量名))

#一个模块中的类能不能反射得到
import my
print(getattr(my,'C')())
if hasattr(my,'name'):
    getattr(my,'name')

要反射的函数有参数怎么办?

print(time.strftime('%Y-%m-%d %H:%M:S'))
print(getattr(time,'strftime')('%Y-%m-%d %H:%M:S'))

hasattr---->判断将要反射的东西是否存在  一般和getattr组合起来使用

import my
print(getattr(my,'C')())
if hasattr(my,'name'):    #判断是否存在
    getattr(my,'name')

setattr---->设置修改变量

delattr 删除一个变量

class A:
    pass
a = A()
setattr(a,'name','nezha')
setattr(A,'name','alex')
print(A.name)
print(a.name)

delattr(a,'name')
print(a.name)
delattr(A,'name')
print(a.name)

面向对象的进阶---->内置方法  

双下方法:  __init__  __dict__  __str__   __repr__  __len__  __del__  __cal__

 

__str__和__repr__

object 里有一个__str__,一旦被调用,就返回调用这个方法的对象的内存地址

repr 是str的备胎,但str不能做repr的备胎

print(obj)/'%s'%obj/str(obj)的时候,实际上是内部调用了obj.__str__方法,如果str方法有,那么他返回的必定是一个字符串

如果没有__str__方法,会先找本类中的__repr__方法,再没有再找上级父类中的__str__。

repr(),只会找__repr__,如果没有找父类的

%s str() 直接打印 实际上都是走的__str__

%r repr() 实际上都是走的__repr__

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)

内置方法有很多,不一定全在object类中

例如:object里面没__len__内置方法(有些东西无法计算长度,object要兼容所有的,因此没len())

class Classes:
    def __init__(self,name):
        self.name = name
        self.student = []
    def __len__(self):        #object里面没__len__内置方法(有些东西无法计算长度,object要兼容所有的,因此没len())
        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__:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的

析构函数: 在删除一个对象之前进行一些收尾工作(引用计数)

class A:
    def __del__(self):   # 析构函数: 在删除一个对象之前进行一些收尾工作
        self.f.close()
a = A()
a.f = open()   # 打开文件 第一 在操作系统中打开了一个文件 拿到了文件操作符存在了内存中
del a          # a.f 拿到了文件操作符消失在了内存中
del a   # del 既执行了这个方法,又删除了变量

__call__:对象()---->相当于执行__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')()

  

  

  

  

 

 

  

 

posted @ 2018-11-09 21:15  KK筑梦人  阅读(99)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3