特殊属性
object中有如下的属性和方法,(格式问题):
['class', 'delattr', 'dir', 'doc', 'eq', 'format', 'ge', 'getattribute', 'gt', 'hash', 'init', 'init_subclass', 'le', 'lt', 'ne', 'new', 'reduce', 'reduce_ex', 'repr', 'setattr', 'sizeof', 'str', 'subclasshook']
class A: pass class B: pass class C(A,B): def __init__(self,name,age): self.name=name self.age=age #创建一个C类的对象 x=C('Jack',20)# 是c类型的实例对象 print(x.__dict__) #绑定的是实例对象的属性字典 print(C.__dict__) print('----------------------------') print(x.__class__) #<class '__main__.C'>输出了对象所属的类型 print(C.__base__) #<class '__main__.A'> A,B谁写在前面,先输出谁 print(C.__bases__) #(<class '__main__.A'>, <class '__main__.B'>) 应该是挨得最近的 print(C.__mro__) #类的层次结构 (<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>) print(A.__subclasses__()) #告诉了A的子类是C,子类的列表
特殊方法
1._ _ add _ 方法在自定义对象“+”时被调用。例如执行c=a+b的底层逻辑相当于d=a._add(b)。运行查看两种方法的结果,都是一样的。
a=20 b=100 c=a+b d=a.__add__(b) print(c) print(d)
通过重写_ _ add _ _方法,使自定义对象拥有“+”功能
class Student: def __add__(self, other): return self.name+other.name def __init__(self,name): #对创建的对象进行初始化,必须要写,不然会报错 self.name=name stu1=Student('张三') stu2=Student('李四') s=stu1+stu2 #实现了两个对象的加法运算(因为Student类中,编写__add__()特殊方法) print(s) s1=stu1.__add__(stu2) #依旧可以这样写 print(s1)
2.通过重写 _ _ len _ _方法,让内置函数len()的参数可以是自定义类型
class Student: def __init__(self,name): #对创建的对象进行初始化,必须要写,不然会报错 self.name=name def __len__(self): return len(self.name) stu1=Student('张三') stu2=Student('李四') lst=[11,22,34,44,54] print(len(lst)) #输出列表长度5 print(lst.__len__()) #5 print(len(stu1)) #2 张三,两个字符长度 本来是不能看对象里面的长度的,但是我定义了这个方法
3._ _ new _ ()用于创建对象
p1、 obj 、slef的id一样;Person类对象和cls的id一致。
因为p1=Person('张三',20)创建实例对象p1,执行时:
首先调到Person()类对象,通过 _ new _ _()把Person传给了cls创建对象,所以Person类对象和cls的id一致。
在object里创建了对象obj,把obj返回给了self,初始化方法执行结束,然后把self给了p1,所以p1、 obj 、slef的id一样。
具体步骤如图所示:
class Person(): def __init__(self,name,age): print('__init__被调用了,self的id值为:{0}'.format(id(self))) self.name=name self.age=age def __new__(cls, *args, **kwargs): print('__new__被调用执行了,cls的id值为{0}'.format(id(cls))) obj=super().__new__(cls) print('创建的对象的id为{0}'.format(id(obj))) return obj print('object这个类对象的id为:{0}'.format(id(object))) print('Person这个类对象的id为:{0}'.format(id(Person))) print('----------------===============-------------------------------') #创建Person类的实例对象 p1=Person('张三',20) print('p1这个Person类的实例对象的id:{0}'.format(id(p1)))
类的浅拷贝与深拷贝
变量的赋值操作 :只是形成两个变量,实际上还是指向同一个对象 (一个的对象,两个变量)
浅拷贝:对象包含的子对象内容不拷贝,因此,源对象与拷贝对象会引用同一个子对象。
class CPU: #CPU类对象 pass class Disk: pass class Computer: #Computer类的【实例对象】会指向这个【类对象】 def __init__(self,cpu,disk): self.cpu=cpu self.disk=disk cpu1=CPU() #创建CPU类对象的实例对象cpu1,有id,type,value三个部分(一个对象) cpu2=CPU() print(cpu1) #(两个变量) print(cpu2) disk=Disk() computer=Computer(cpu1,disk) import copy print(disk) computer2=copy.copy(computer) #只拷贝一份源对象,即Computer类的【实例对象】 print(computer,computer.cpu,computer.disk) print(computer2,computer2.cpu,computer2.disk) #仔细观察,子对象的id没有变化
守先创建三个类对象:CPU、Disk、Computer,
创建CPU类对象的实例对象,其中有id,type,value三个部分,名为cpu1的变量中存储了CPU实例对象的id。
创建Disk类对象的实例对象,其中有id,type,value三个部分,名为disk的变量中存储了Disk实例对象的id。
Computer类对象的实例对象的value有cpu、disk ,名为computer的变量存储了Computer的id地址。
compter.cpu指向CPU的实例对象,compter.disk指向Disk的实例对象。
当使用copy.copy(computer) 浅拷贝一份源对象,即Computer实例对象,会有一个computer2的变量存储了id(0x8190)而CPU、Disk不拷贝,compter2.cpu指向CPU的实例对象,compter2.disk指向Disk的实例对象。
深拷贝:使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象,源对象和拷贝对象所有的子对象也不相同。
print('-----------------------------接上上面的浅拷贝代码---------------------------------') print() computer3=copy.deepcopy(computer) print(computer,computer.cpu,computer.disk) print(computer3,computer3.cpu,computer3.disk) #仔细观察,所有的实例对象的id都发生了变化
模块
什么是模块:新建的一个.py文件,名称尽量不要与Python自带的标准模块名称相同。
导入模块:
import 模块名称 [as别名]
from 模块名称 import 函数/变量/类
1.以主程序的方式运行
首先创建calc2.py。点击运行,结果没有问题。
def add(a,b): return a+b print(add(10, 20))
然后创建了一个新的模块demo7.Py。点击运行,发现还执行了calc2的结果
import calc2 print(calc2.add(100,200))
在calc2中引入name == 'main':只有在calc2是主程序时才会运行print(add(10, 20))
def add(a,b): return a+b if __name__ == '__main__': print(add(10, 20))
Python中的包
包是一个分成次的目录结构,它将一组织功能相近的模块组织在一个目录下。
作用:1.代码规范 2.避免模块名称冲突
创建:点击新建Python package,每一个包下面都有一个_ init .py文件
包与 目录 的区别:
1 . 包含_init.py文件的目录称为包
2.目录里面通常不包含init.py文件
在一个新建的package中新建一个module_A.py。 在另一个模块中导入package1 包
import package1.module_A as ma #ma是这个的一个别名 print(ma.a) #10
Python中常用的内置模块
1.sys :Python解释器及其环境操作相关的标准库
print() import sys print(sys.getsizeof(24)) #字节数 28 print(sys.getsizeof(45)) #28 print(sys.getsizeof(True)) #28 print(sys.getsizeof(False)) #24
2.time :与时间相关的标准库
print() import time print(time.time()) print(time.localtime(time.time()))
3.os提供了访问操作系统服务功能的标准库
4.calendar提供了日期相关的各种函数标准库
5.urllib :用来读取网上的(服务器)的数据标准库
print() import urllib #会跳到init里面,说明这是一个包 import urllib.request #这个包里有一个request模块 print(urllib.request.urlopen('http://www.baidu.com').read()) #这个爬虫的时候才会用到
6.json用于使用JSON序列化和反序列化对象
7.re在字符串中执行正则表达式匹配和替换
8.math数***算
9.decimal :精确地控制运算精度、有效数位数、四舍五入的十进制计算
10.logging灵活的记录事件、错误、警告、调试信息等日志信息的功能
第三方模块的安装与使用
pip install 模块名
Windows+R,输入cmd,回车,输入pip install schedule,回车。
import schedule #可用于定时发送邮件 import time def job(): print('写作业') schedule.every(3).seconds.do(job)#没三秒执行一次schedule模块 while True: schedule.run_pending() time.sleep(1)
可在pycharm中安装,步骤如下:
settings---->Project:...---->Project Interpreter,在界面的右边你可以看到一个已安装的Package的信息的表格
如果目标Package不在此表中,点击该表的右上方的+号
在搜索框内搜索目标Package,再点击左下角的install Package即可