前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python3--面向对象的进阶

python3--面向对象的进阶

作者头像
py3study
发布2018-08-02 16:32:40
2830
发布2018-08-02 16:32:40
举报
文章被收录于专栏:python3

昨日内容练习

代码语言:javascript
复制
class A:
    def func1(self):pass  # func1 普通方法
    @classmethod
    def func2(self):pass  # func2 类方法
    @staticmethod
    def func3(self):pass  # func3 静态方法

# func1 普通方法 对象和类绑定的过程
a = A()
b = A()
print(A.func1)  # 3个地址都不一样
print(a.func1)
print(b.func1)

# func2 类方法 由于不适用对象内存空间中的属性,
# 所以不会将对象和方法绑在一起,而是将类和方法绑在一起
print(A.func2)
print(a.func2)  # 对象能找到类,类里面绑着方法
print(b.func2)

# func3 静态方法 不是绑定方法 没有和对象或者类发生任何绑定关系
print(A.func3)
print(a.func3)
print(b.func3)

执行结果

1 普通方法,func1结果

<bound method A.func1 of

<bound method A.func1 of

2 类方法,func2结果

<bound method A.func2 of

<bound method A.func2 of

<bound method A.func2 of

3 静态方法,func3结果

isinstance(对象名,类名) 返回True,False

isinstance(obj,cls)检查obj是否是类cls的对象

例子

代码语言:javascript
复制
class A:pass
class B(A):pass
b = B()
print(isinstance(b, A))  # 能够检测到继承关系
print(isinstance(b, B))
print(type(b) is A)
print(type(b) is B)  # type只单纯的判断类

执行结果

True

True

False

True

issubclass(子类名,父类名) 返回True,False

issubclass(sub,super)检查sub类是否是super类的派生类

例子,单继承

代码语言:javascript
复制
class A:pass
class B:pass
class C(B):pass
class D(C):pass
print(issubclass(C,B))  # 判断C是不是B的子类
print(issubclass(D,C))  # 判断D是不是C的子类
print(issubclass(D,B))  # 判断D是不是C的子类
print(issubclass(D,A))  # 判断D是不是A的子类

执行结果

True

True

True

False

例子2,多继承

代码语言:javascript
复制
class A:pass
class B:pass
class C(A,B):pass
class D(C):pass

print(issubclass(C,A))  # 判断C是不是A的子类
print(issubclass(C,B))  # 判断C是不是B的子类
print(issubclass(D,B))  # 判断D是不是B的子类
print(issubclass(D,A))  # 判断D是不是A的子类

执行结果

True

True

True

True

面向对象进阶(反射,非常重要的知识点*******7星)

1 什么是反射

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问,检测和修改它本身状态或行为的一种能力(自省),它首先被程序语言的设计领域所采用,并在Lisp和面向对象取得了成绩

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

四个可以实现自省的函数

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

反射

正常情况下如果可以拿到这个变量, 那么如有这个变量的字符串形式,就是用反射可以获取到这个值

使用字符串数据类型的变量名 访问一个命名空间中的名字

找一个属性,直接就可以找到这个属性的值

找一个方法,找到的是这个方法的内存地址

getattr 使用字符串数据类型的变量名 访问一个命名空间中的名字

源代码

代码语言:javascript
复制
def getattr(object, name, default=None): # known special case of getattr
    """
    getattr(object, name[, default]) -> value
    
    Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
    When a default argument is given, it is returned when the attribute doesn't
    exist; without it, an exception is raised in that case.
    """
    pass

例子

代码语言:javascript
复制
class A:
    role = 'person'  # 静态属性
    def func(self):
        print('*'*10)
print(A.__dict__['role'])  # 查看静态属性的值
ret = input('>>>')  # 用户输入role
print(A.__dict__[ret])  # 实际上就是执行了最上面的print

执行结果

person

>>>role

person

那么如何让用户输入func然后去执行类里面的方法func呢?

代码语言:javascript
复制
class A:
    role = 'person'  # 静态属性
    def func(self):
        print('*'*10)
ret = input('>>>')  # 用户输入func
# 这里要用到字符串拼接+eval函数才能实现
s = 'A'
ss = s + '.' + ret
eval(ss)(1)

执行结果

>>>func

**********

这样很麻烦,也不安全,还有什么方法呢?

getattr()  从命名空间中获取这个名字对应的值

代码语言:javascript
复制
class A:
    role = 'person'  # 静态属性
    def func(self):
        print('*'*10)

# 从A的命名空间里找一个属性,直接就可以找到这个属性的值
# 通俗点就是需要获取谁(func),就是getattr(A,'func') getattr(类,'属性名')
print(getattr(A, 'role'))

a = A()  # 实例化一个对象a
# 从A的命名空间里面找一个方法,找到的是这个方法的内存地址,如果要执行这个方法,在后面加()
print(getattr(a, 'func'))
getattr(a, 'func')()

#getattr如何让用户输入一个类中的方法名,并执行
ret = input('>>>:')
getattr(a, ret)()  # getattr(a, ret)实际上获取的就是func方法的内存地址,后面加()就表示执行

执行结果

person

<bound method A.func of

**********

>>>:func

**********

例2

代码语言:javascript
复制
class A:
    role = 'Person'
    def __init__(self):
        self.money = 500
    def func(self):
        print('*'*10)
a = A()
print(a.func)  # 打印a.func的内存地址
getattr(a, 'func')()  # 使用getattr获取名字对应的值,名字加()就表示执行这个方法
print(getattr(a, 'money'))  # 使用getattr获取名字对应的值

执行结果

<bound method A.func of

**********

500

hasattr() 判断一个命名空间中有没有这个名字

源码

代码语言:javascript
复制
def hasattr(*args, **kwargs): # real signature unknown
    """
    Return whether the object has an attribute with the given name.
    
    This is done by calling getattr(obj, name) and catching AttributeError.
    """
    pass

例1

代码语言:javascript
复制
class A:
    role = 'person'
    def func(self):
        print('py3study.com')

a = A()
print(hasattr(a, 'r'))  # 也可以写成 print(hasattr(A, 'r'))
print(hasattr(a, 'role'))
print(hasattr(a, 'func'))

执行结果

False

True

True

hasattr()经常与getattr()一起用,首先判断一个命名空间中有没有这个名字,有的话就用getattr获取这个名字对应的值

示例

代码语言:javascript
复制
class A:
    role = 'person'
    def func(self):
        print('py3study.com')

ret = input('>>>')
if hasattr(A, ret):  # 判断是否存在
    print(getattr(A, ret))  # 如果存在则打印内存地址
if hasattr(A, ret):
    func = getattr(A, ret)  # 如果存在则执行这个方法
    func(1)
else:
    print('error')  # 不存在则报错

执行结果

>>>func

py3study.com

类使用类命名空间中的名字

对象使用对象能用的方法和属性

模块使用模块中的名字

导入os模块,利用getattr获取os模块中'rename'对应的值,os.rename('old','new')执行改文件名的操作

import os;getattr(os, 'rename')('user', 'user_info') 

导入time模块,利用getattr获取time模块中'time'对应的值,print(time.time())打印时间戳

import time;print(getattr(time, 'time')())

从自己所在的模块中使用自己名字

示例

代码语言:javascript
复制
def login():
    print('执行login功能')

def  register():
    print('执行register功能')

import sys
print(sys.modules['__main__'])  # 打印当前文件的路径,一个.py文件就相当于一个模块
func = input('>>>')
if hasattr(sys.modules['__main__'], func):  # 判断当前模块中的命名空间,是否有用户输入的这个名字
    getattr(sys.modules['__main__'], func)()  # 存在的话执行用户输入的名字加()这个函数

执行结果

>>>login

执行login功能

类使用类命名空间中的名字

getattr(类名,'名字')

对象使用对象能用的方法和属性

getattr(对象名,'名字')

模块使用模块中的名字

导入模块

getattr(模块名,'名字')

从自己所在的模块中使用自己名字

import sys

getattr(sys.modules['__main__'],名字)

getattr一定要和hasattr配合使用

反射 :4个内置函数

getattr  # 从命名空间中获取这个名字对应的值

hasattr  # 判断一个命名空间中有没有这个名字  

setattr  # 修改和新建

delattr  # 删除一个属性

setattr,delattr

setattr源码

代码语言:javascript
复制
def setattr(x, y, v): # real signature unknown; restored from __doc__
    """
    Sets the named attribute on the given object to the specified value.
    
    setattr(x, 'y', v) is equivalent to ``x.y = v''
    """
    pass

delattr源码

代码语言:javascript
复制
def delattr(x, y): # real signature unknown; restored from __doc__
    """
    Deletes the named attribute from the given object.
    
    delattr(x, 'y') is equivalent to ``del x.y''
    """
    pass

增删改 对象属性

代码语言:javascript
复制
class A:
    def __init__(self, name):
        self.name = name

    def wahaha(self):
        print('噢噢噢噢哦哦哦')
a = A('Sam')
print(a.name)
a.wahaha()
print(a.__dict__)

# 使用setattr: 无则增加有则修改的原则
setattr(a, 'age', 18)  # 给a对象新增一个属性
print(a.__dict__)
a.wahaha()  # 执行wahaha()方法

# 使用setattr: 无则增加有则修改的原则
setattr(a, 'name', 'Jack')  # 修改a对象的name属性为Jack
print(a.__dict__)

del a.name  # 删除a对象的name属性
print(a.__dict__)

# 使用delattr删除
delattr(a, 'age')
print(a.__dict__)

执行结果

Sam

噢噢噢噢哦哦哦

{'name': 'Sam'}

{'name': 'Sam', 'age': 18}

噢噢噢噢哦哦哦

{'name': 'Jack', 'age': 18}

{'age': 18}

{}

例2

代码语言:javascript
复制
class A:
    def __init__(self, name):
        self.name = name

    def  wahaha(self):
        print('aaaaaaaaaaa')

def qqxing(self):
    print('qqqqqqqqq')

a = A('Tom')
setattr(a, 'qqxing', qqxing)  # setattr把函数qqxing 加到类里面去了
a.qqxing(a)

# 使用getattr函数从命名空间中获取这个名字对应的值
getattr(a, 'qqxing')(a)

执行结果

qqqqqqqqq

qqqqqqqqq

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018/04/18 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档