赞
踩
python是一门面向对象的语言,拥有三大特性:
继承:子类继承父类的属性和方法,使得子类拥有父类的属性及方法。
封装:将对象的属性和方法隐藏起来,提供对外公开接口。
多态:同一个函数在不同场景下有不同的表现形式。
1.定义:
class Car():
...属性和方法....
2.创建对象(也叫类实例化)
对象名 = 类()
3.调用方法或属性
对象名.方法或属性()
4.self关键字,作用:用来指向实例对象本身
def func(self):
self.color = 'red'
当创建对象时对自动触发,一般用于初始化
1.无参:
class Car:
def __init__(self):
self.age = 18
self.name = '小红'
2.有参:
#定义:
class Car:
def __init__(self, name, age):
#调用:
my_car = Car('wc',14)
print(my_car.name,my_car.age)
默认打印对象时调用
class Car:
def __init__(self):
self.age = 18
self.name = '小红'
def __str__(self):
return f'{self.age}, {self.name}'
car = Car()
print(car)
默认删除对象时(调用del删除对象或文件执行结束后),python解释器会默认调用该方法
class Car:
def __init__(self):
self.age = 18
self.name = '小红'
def __del__(self):
print('删除删除')
car = Car()
del car
class 子类名(父类):
pass
#子类可以使用父类中的属性和方法,提高代码复用率
class 子类名(父类1, 父类2, ....)
pass
# 当一个类有多个父类时,默认使用第一个父类的同名属性和方法,可以使用__mro__或者mro()查看调用的先后顺序:
print(子类名.__mro__)
print(子类名.mro())
重写也叫做覆盖,当子类属性或方法和父类的属性或方法名相同时,子类重写定义这些属性或方法
1. 父类名.父类方法名()
2. 子类对象.父类方法名()
3. super().父类方法名()
定义和获取私有属性
self.__name
# 外界调用时只能通过定义的get、set方法
def set__name(self, name)
self.__name = name
def get__name(self)
return self.__name
1.有继承
2.函数重写
3.父类引用指向子类对象(子类对象传给父类对象调用者)
class Animal(object): def speak(self): print("animal 嗯嗯 ") pass class Dog(Animal): def speak(self): print('汪汪汪') class Cat(Animal): def speak(self): print('喵喵喵') # def make_noise(animal): def make_noise(animal:Animal): animal.speak() if __name__ == '__main__': mydog = Dog() mycat = Cat() animal = Animal() make_noise(mydog) make_noise(mycat) make_noise(animal)
如果说继承是子类可以调用父类的方法的话,多态可以说是父类可以使用子类的方法
抽象类其实也可以叫做接口
抽象类其实就是父类方法的方法体中是pass
class Animal(object):
def make_voice(self):
pass
class Dog(Animal):
def make_voice(self):
print('汪汪汪')
class Cat(Animal):
def make_voice(self):
print('喵喵喵')
类方法其实就是类拥有的方法,使用装饰器@classmethod来装饰
格式:
@classmethod
def 类方法名(cls):
...
#调用:
类名.类方法名() 或者对象名.类方法名()
使用@staticmethod装饰器来装饰的方法,应用场景在方法体固定不变的方法上
@staticmethod
def 静态方法名():
...
#调用:
类名.类方法名() 或者对象名.类方法名()
拷贝可以理解为以原对象围殴模板,复制出了一个新对象,指向一个新的内存地址,虽然拷贝后的对象和原对象值一摸一样,但是内存地址指向不同。
可变数据类型:列表、字典、集合
不可变类型:字符串、数值型(int、float)、元组
对于可变数据类型:
浅拷贝只拷贝第一层,内层依旧指向同一个内存地址
深拷贝全部拷贝
对于不可变数据类型:
不管是深拷贝还是浅拷贝,都是全部拷贝,可以理解为都是引用赋值,指向统同一内存空间
1.函数名存放的是函数所在内存空间的地址
2.函数名()执行的是函数所在内存空间地址中的代码
3.函数名可以像普通变量一样赋值。
1.定义:
def 外部函数(外部参数):
def 内部函数(内部参数):
...
return 内部函数名
# 调用
对象名 = 外部函数名(外部函数参数)
对象名(内部函数参数)
2.闭包的作用: 闭包可以保存函数中的变量,而不会随着调用完函数而被销毁。
3.内部函数构成条件:
nonlocal 外部函数变量名
装饰器就是在不改变原有函数的基础上,给原有函数增加额外功能。
def func_out(fn):
def func_in():
额外功能
fn()
return func_in
@func_out
def fn():
原函数功能
#调用
fn()
口诀:
原函数有返回值,那内部函数中也得有原函数返回值
原函数有参数,则内部函数和内部函数调用的原函数也有参数值
import socket
if __name__ == '__main__':
# 1.创建客户端套接字对象 socket.AF_INET表示ipv4 socket.SOCK_STREAM表示tcp
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.和服务端套接字建立连接
tcp_client_socket.connect(("192.168.33.65", 8080))
# 3.发送数据
tcp_client_socket.send("nihao".encode(encoding="utf-8"))
# 4.接收数据 recv阻塞等待数据的到来
recv_data = tcp_client_socket.recv(1024)
print(recv_data.decode(encoding="utf-8"))
# 5.关闭客户端套接字
tcp_client_socket.close()
import socket if __name__ == '__main__': # 1.创建服务端套接字对象 tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #端口复用 tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) # 2.绑定ip地址和端口号 如果bind中的ip元素设置为“”,默认为本机ip tcp_server_socket.bind(("192.168.33.65", 8889)) # 3.设置监听 127:代表服务器等待排队链接的最大数量 tcp_server_socket.listen(128) while True: # 4.通过accept从linux内核中获取已经建立好的连接 conn_socket, ip_port = tcp_server_socket.accept() print("客户端地址: ", ip_port) # 5.接受数据 recv_data = conn_socket.recv(1024) print("接收到的数据: ", recv_data.decode(encoding="GBK")) # 6.发送数据 conn_socket.send("客户端你的数据我收到了".encode(encoding="GBK")) # 7.关闭套接字 conn_socket.close() tcp_server_socket.close() # 注意 服务器一般不主动关闭连接,若客户端把连接关闭,则服务端才会关闭连接
进程:cpu资源分配的最小单位,一个运行的程序就是一个进程
工作方式: 先创建一个主进程,通过主进程创建子进程
创建:
import multiprocessing
# 函数不带参数:
p1 = multiprocessing.Process(target=函数名)
# 函数带参数:#使用args元组形式传参时,要注意和原函数参数顺序对应
p1 = multiprocessing.Process(target=函数名,args=元组形式或者kwards = 字典形式)
p1.start()
#注意:若要主进程等待子进程完成
子进程.join()
# 获取当前进程编号:
1.os.getpid()
2.multiprocessing.current_process().pid
# 获取父进程编号:
os.getppid()
线程:cpu调度的基本单位
创建:
# 1.导包
import threading
# 2.通过线程类创建线程对象
线程对象 = threading.Thread(target=任务名)
# 3.启动线程执行任务
线程对象.start()
# 注意:若要主进程等待子进程完成
子进程.join()
# 获取当前线程的id:
tid = threading.current_thread()
# 设置守护主线程:
1.创建线程参数daemoin=True
2.线程对象.setDaemon(True)
执行顺序:线程之间执行是无序的
多个线程共享全局变量出现数据错误问题:
造成原因:线程1读内存空间数据以后,还没有来得及更新内存空间,结果线程2又读 内存空间,造成两个线程对同一内存空间进行了读写,重复,解决方法:加互斥锁,操作:
# 1.创建锁对象:
lock = threading.Lock()
# 2.上锁:
lock.acquire()
# 3.释放锁:# 若不适当的释放锁,会造成死锁问题
lock.release()
语法:
# 无论是否会出现异常,最终都会自动运行文件关闭的操作 f就是上下文管理器
with open('./a.txt', 'w', encoding='utf8') as f :
f.write('abcdefg')
with语句管理的对象就是上下文管理器。
实现原理:(实现了__enter__和__Exit__方法)
__enter__上文方法:返回一个操作对象
__exit__下文方法:with语句执行完成后自动执行,即使出现异常也会执行。
定义:
generator = (i * 2 for i in range(5))
# 迭代下一个元素:
next(generator)
# 遍历
for i in generator:
print(i)
定义:
def myGenerator():
for i in range(5):
yield i
yield关键字作用:返回后面的数、挂起等待next激活
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。