特殊属性

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即可