python3--面向对象的进阶

昨日内容练习

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的对象

例子

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类的派生类

例子,单继承

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,多继承

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 使用字符串数据类型的变量名 访问一个命名空间中的名字

源代码

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

例子

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呢?

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

执行结果

>>>func

**********

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

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

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

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() 判断一个命名空间中有没有这个名字

源码

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

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获取这个名字对应的值

示例

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

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

示例

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源码

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源码

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

增删改 对象属性

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

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏青玉伏案

窥探Swift编程之错误处理与异常抛出

在Swift 2.0版本中,Swift语言对其错误处理进行了新的设计,当然了,重新设计后的结果使得该错误处理系统用起来更爽。今天博客的主题就是系统的搞一下Swi...

1945
来自专栏xcywt

《Linux命令行与shell脚本编程大全》第十七章 创建函数

可以将shell脚本代码放进函数中封装起来,这样就能在脚本中的任何地方多次使用它了。 17.1 基本的脚本函数 函数:是一个脚本代码块,可以为其命名并在代码中任...

18910
来自专栏编程

Python面向对象6:​isinstance、super、有序字典

1、isinstance(对象名,类),查看对象是不是类的实例。 案例1:isinstance(对象名,类) classFoo: print('hh') obj...

1938
来自专栏java一日一条

JVM 进行线程同步背后的原理

所有的 Java 程序都会被翻译为包含字节码的 class 文件,字节码是 JVM 的机器语言。这篇文章将阐述 JVM 是如何处理线程同步以及相关的字节码。

711
来自专栏xingoo, 一个梦想做发明家的程序员

数字按照不同格式转换成字符串

  如果自己写函数,不使用itoa怎么判断呢?   我们用通常的办法,对数字进行每位的除商,得到后与字符'0'相加。 flag = 0; ...

20610
来自专栏一个爱吃西瓜的程序员

Python基础学习-if 语句

一:条件测试 1:检查是否相等 例: ? 输出: ? 2:使用and & or检车多个条件 例: ? 输出: ? 3:检查特定值是否包含在列表中 例: ? 输...

3516
来自专栏程序员互动联盟

【编程基础】C语言的变量-新手必备

大家在初学C语言的时候对各种变量之间的区别以及存储布局可能都有很多疑问,造成在使用变量的时候可能会遇到错误的地方。这里做一个简单的总结。 首先是全局变量和静态变...

36910
来自专栏Python小屋

Python面向对象程序设计中属性的作用与用法

公开的数据成员可以在外部随意访问和修改,很难保证用户进行修改时提供新数据的合法性,数据很容易被破坏,并且也不符合类的封装性要求。解决这一问题的常用方法是定义私有...

2464
来自专栏WebDeveloper

php缓冲区与header函数之间的秘密

我们在实际的开发中,是否听说过在header之前不能有任何的实际输出。甚至有的认为header函数必须写在代码的最前面。可是你是否试验过header函数之前输出...

1212
来自专栏zingpLiu

浅谈JavaScript词法分析步骤

JavaScript代码运行前有一个类似编译的过程即词法分析,词法分析主要有三个步骤:

1045

扫码关注云+社区