python基础7_2-类的特殊成员方法、动态导入模块、断言(assert)

1、类的特殊成员方法

  1. _ modle _: 表示当前操作对象在哪个模块
    _ class _: 表示当前操作的对象的类是什么
class C:

    def __init__(self):
        self.name = 'severen'
from lib.aa import C

obj = C()
print(obj.__module__)  # 输出 lib.aa,即:输出模块
print(obj.__class__)      # 输出 lib.aa.C,即:输出类
  1. _ doc _: 打印描述信息
  2. _ call _: 构造方法的执行是由创建对象触发的,即对象 = 类名();而对于__call___方法的执行是由对象后面加(),即对象()或类()()
  3. _ dict _: 查看类中或对象中所有的成员。通过类打印类里面的所有属性,不包括实例属性;通过实例调用,打印所有实例属性,不包括类属性
  4. _ str _: 打印对象时,默认输出该方法的返回值
# Author: Mr.Xue
# 2019.10.29

class Dog(object):
	"""this is a class: Dog (描述信息)"""
	def __init__(self, name):
		self.name = name
		
	def eat(self, food):
		print("%s is eating %s" % (self.name, food))	

	def __call__(self, *avgv, **kwargv):
		print("hello", avgv, kwargv)

	def __str__(self):
		return "helllo" + self.name
		
print(Dog.__dict__) # 查看类中所有的成员
print(Dog("bob").__dict__) # 查看对象中的所有成员

d = Dog("Bob")

print(d) #打印对象,输出__str__方法的返回值

print(d.__doc__) # 打印描述信息

d() # 执行__call__()方法

运行结果如下:

xue@xue-MacBookAir:~/python_learn$ python3 static_method.py 
{'__init__': <function Dog.__init__ at 0x7f05cadd5730>, 'eat': <function Dog.eat at 0x7f05cadd57b8>, '__str__': <function Dog.__str__ at 0x7f05cadd58c8>, '__weakref__': <attribute '__weakref__' of 'Dog' objects>, '__doc__': 'this is a class: Dog (描述信息)', '__module__': '__main__', '__call__': <function Dog.__call__ at 0x7f05cadd5840>, '__dict__': <attribute '__dict__' of 'Dog' objects>}
{'name': 'bob'}
hellloBob
this is a class: Dog (描述信息)
hello () {}
  1. _ _ getitem _ _ 、_ _ setitem _ _ 、_ _ delitem _ _ : 用于索引操作
class Foo(object):
	def __init__(self):
		self.data = {}
		
	def __getitem__(self, key):
		print('__getitem__', key)
		return self.data.get(key)
	
	def __setitem__(self, key, value):
		print('__setitem__', key, value)
		self.data[key] = value
		
	def __delitem__(self, key):
		print('__delitem__', key)

obj = Foo()
obj['name'] = 'xue' # 调setitem
print(obj.data)
print(obj['name']) # 调getitem
del obj['name'] # 调delitem
  1. _ new _ 和 _ metaclass _
class Foo(object):
 
	def __init__(self,name):
        self.name = name
        
f = Foo("severen")

上述代码中,f 是通过 Foo 类实例化的对象,其实,不仅 f 是一个对象,Foo类本身也是一个对象,因为在Python中一切事物都是对象

如果按照一切事物都是对象的理论:f对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法 创建的。

printtype(f)# 输出:<class '__main__.Foo'>     表示,obj 对象由Foo类创建
printtype(Foo)# 输出:<type 'type'>              表示,Foo类对象由 type 类创建

所以,f对象是Foo类的一个实例,Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建。

在这里补充一下类的创建方式其实有两种,如下

# 第1种方式
class Foo(object):
  
    def func(self):
        print('hello severen')
# ----------------------------------
# 第2种方式
def func(self):
	print("hello world")

def __init__(self, name):
	self.name = name
	print("---")
	
Foo = type("Foo", (object,), {"func": func, '__init__': __init__})

f = Foo('Bob')
f.func()

到这里,我们知道了类默认是由 type 类实例化产生,那么type类对象又是由谁来创建产生的呢?type类中如何实现的创建类?类又是如何创建对象?
答:类中有一个属性 _ metaclass_,其用来表示该类由 谁 来实例化创建,所以,我们可以为 _ metaclass_ 设置一个type类的派生类,从而查看 类 创建的过程。

# Author: Mr.XUe
# 2019.10.30

class MyType(type):
	def __init__(self, what, base=None, dict=None):
		print("--MyType init--")
		super(MyType, self).__init__(what, base, dict)
		
	def __call__(self, *argv, **kwargv):
		print("--MyType call--")
		obj = self.__new__(self, *argv, **kwargv)
		# obj.data = {'name': 111}
		self.__init__(obj)	

class Foo(object):
	__metaclass__ = MyType
	
	def __init__(self, name):
		self.name = name
		
	def __new__(cls, *argv, *kwargv):
		# 这一块可以添加自己的小功能
		return object.__new__(cls, argv, kwargv) # 继承父类的__new__方法	
		
obj = Foo("bob")

在这里插入图片描述
metaclass参考文章:https://stackoverflow.com/questions/100003/what-are-metaclasses-in-python

2、动态导入模块

好处:简化导入自定义模块的导入步骤
举例:在A目录下有lib文件夹和dong态导入模块.py文件,在lib文件夹下又有__init__.py和aa.py两个文件,init.py文件没有内容,aa.py的代码如下:

# Author: Mr.Xue
# 2019.10.31
# aa.py

class C(object):
	def __init__(self):
		self.name = 'xue'

现在我们的需求是dong态导入模块.py文件需要去导入aa.py文件。
逻辑分析:按照正常的逻辑,我们首先需要去获取到dong态导入模块.py文件的父目录,在通过父目录我们可以找到lib,最后通过lib才可以找到aa.py,程序代码如下:

# Author: Mr.Xue
# 2019.10.31
# dong态导入模块.py

#!usr/bin/python3

import os,sys

# __file__: 当前文件
# os.path.abspath: 获取当前文件的绝对路径
# os.path.dirname: 获取上一级的路径
BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # BASE_DIR现在A所在的绝对路径

sys.path.append(BASE_DIR) # 将该路径写入环境

from lib import aa # 导入aa.py文件

print(aa.C().name) # 打印C类的对象属性name

上面这一种导入的方式写起来就比较繁琐复杂,现在我们来看看动态导入模块的写法,代码如下:

# Author: Mr.Xue
# 2019.10.29
# dong态导入模块.py

# ------解释器自己内部使用的
#lib = __import__("lib.aa")
#print(lib)
#print(lib.aa.C().name)


# -------官方建议使用的
import importlib # 导入importlib库
aa = importlib.import_module("lib.aa") # 导入aa.py文件
#print(aa) # 打印aa的内存地址
print(aa.C().name) # 打印C类的对象属性name

是不是很简单,短短的三行代码就完成了,逻辑上也很简单。两种方式的运行结果都是一样的,如下所示:

xue@xue-MacBookAir:~/python_learn/A$ python3 dong态导入模块.py 
xue

3、assert 断言

使用断言可以创建更稳定、品质更好且不易于出错的代码。当需要在一个值为FALSE时中断当前操作的话,可以使用断言
看一个简单的例子:

# Author: Mr.Xue
# 2019.10.31

class A(object):
	def __init__(self, name):
		self.name = name
	
a = A("xue")
# 判断name属性的值是不是str类型的,如果是,执行下一步,否则,阻断在这里
assert type(a.name) is str 
print(a.name)

上面的条件成立,所以会打印name的值,“xue”;否则,阻塞

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值