Fork me on Github Fork me on Gitee

python程序设计(二):python进阶

python进阶

函数与函数式编程

函数的定义与调用

返回斐波那契数列中小于整数n的所有值

def fib(n):
    pass
fib(1000)

python中的函数,用def关键字定义.函数不需要返回值类型,不需要参数类型

函数的参数

函数参数的集中类型:
位置参数(positional arguments):形参和实参数量相同,位置一致.
缺省参数(default arguments):形参有默认值,有缺省参数的形参要在位置参数之后.
关键字参数(keyword arguments):实参顺序可以和形参顺序不一致,避免了用户需要牢记位置参数顺序的麻烦
可变参数(variable-length arguments):*parameter用来接受多个实参并将其放在元组中.**parameter接收多个关键参数并存放到字典中

位置参数:

def func(a,b,c):
    print(a,b,c)
func(1,2)
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

c:\Users\Tenerome\Desktop\python\lesson.ipynb Cell 45 in <cell line: 3>()
      <a href='vscode-notebook-cell:/c%3A/Users/Tenerome/Desktop/python/lesson.ipynb#X63sZmlsZQ%3D%3D?line=0'>1</a> def func(a,b,c):
      <a href='vscode-notebook-cell:/c%3A/Users/Tenerome/Desktop/python/lesson.ipynb#X63sZmlsZQ%3D%3D?line=1'>2</a>     print(a,b,c)
----> <a href='vscode-notebook-cell:/c%3A/Users/Tenerome/Desktop/python/lesson.ipynb#X63sZmlsZQ%3D%3D?line=2'>3</a> func(1,2)


TypeError: func() missing 1 required positional argument: 'c'

这个就是positional 参数,缺少时报错

缺省参数:

def func1(a,b,c=1):
    print(a,b,c)
func1(2,3)
2 3 1

定义函数时就对形参赋值,就是缺省参数,后面传实参会覆盖

关键字参数:

def func2(a,b,c):
    print(a,b,c)
func2(c=3,a=1,b=2)
1 2 3

可以看到调用的时候没有按形参顺序来,但是用关键字(形参名)来调用的,就可以忽略顺序

def stu(country='中国',name):
    print("%s,%s" %(name,country))
stu('美国','Tom')
  Input In [7]
    def stu(country='中国',name):
                             ^
SyntaxError: non-default argument follows default argument

有缺省值的参数必须放位置参数后面

def stu(name,country='中国'):
    print("%s ,%s" %(name,country))
stu('美国','Tom')
美国 ,Tom

可变参数:

变量的作用域

函数体外部的变量:全局变量
内部:局部变量

函数内可以调用全局变量

x=100
def f():
    print(x)
f()
100

在函数内部的变量赋值操作,该变量就是局部变量.

x=100
def f():
    print(x)
    x=200
    print(x)
f()
---------------------------------------------------------------------------

UnboundLocalError                         Traceback (most recent call last)

c:\Users\Tenerome\Desktop\python\lesson.ipynb Cell 63 in <cell line: 6>()
      <a href='vscode-notebook-cell:/c%3A/Users/Tenerome/Desktop/python/lesson.ipynb#Y116sZmlsZQ%3D%3D?line=3'>4</a>     x=200
      <a href='vscode-notebook-cell:/c%3A/Users/Tenerome/Desktop/python/lesson.ipynb#Y116sZmlsZQ%3D%3D?line=4'>5</a>     print(x)
----> <a href='vscode-notebook-cell:/c%3A/Users/Tenerome/Desktop/python/lesson.ipynb#Y116sZmlsZQ%3D%3D?line=5'>6</a> f()


c:\Users\Tenerome\Desktop\python\lesson.ipynb Cell 63 in f()
      <a href='vscode-notebook-cell:/c%3A/Users/Tenerome/Desktop/python/lesson.ipynb#Y116sZmlsZQ%3D%3D?line=1'>2</a> def f():
----> <a href='vscode-notebook-cell:/c%3A/Users/Tenerome/Desktop/python/lesson.ipynb#Y116sZmlsZQ%3D%3D?line=2'>3</a>     print(x)
      <a href='vscode-notebook-cell:/c%3A/Users/Tenerome/Desktop/python/lesson.ipynb#Y116sZmlsZQ%3D%3D?line=3'>4</a>     x=200
      <a href='vscode-notebook-cell:/c%3A/Users/Tenerome/Desktop/python/lesson.ipynb#Y116sZmlsZQ%3D%3D?line=4'>5</a>     print(x)


UnboundLocalError: local variable 'x' referenced before assignment

也就是说,在函数内,一旦引用了全局变量,就不能在函数内对全局变量赋值

但是可以先赋值再引用,这时两个x并不是同一个,相当于两个变量,一个全局,一个局部,但是有相同的变量名

x=100
def f():
    x=200
    print(id(x))
f()
id(x)
2413391733392
2413391730128

想要在函数内真正调用全局变量,可以用global声明

x=100
def f():
    global x
    x=200
    print(id(x))
f()
id(x)
2413391733392
2413391733392

python支持使用nonlocal关键字定义一宗介于全局和局部之间的变量,成为闭包作用域变量.关键字nonlocal声明的变量会引用距离最近的非全局作用域的变量(闭包变量或局部变量).要求声明的变量已经存在.关键字nonlocal不会创建新变量

lambda表达式
def fsum(x,y):
    return x+y

像上面的函数,只是很简单的功能,就定义了函数.lambda表达式就是用来代替简单的函数的

基本结构lambda left : right.其中left是参数,right是返回值.

f=lambda x,y : x+y
f(3,5)
8

lambda表达式就是把简单的函数改成无函数体的形式,只有参数和返回值.返回值用表达式的形式.只要能改成这样的结构的函数,都可以写成lambda表达式的形式

函数式编程

函数式编程就是把函数作用于一个或多个序列,来实现一些功能

① 内置函数map()可以将一个函数作用到一个或多个序列或迭代器对象上,返回可迭代的map对象

map()会把seq中的元素一个个作用在func()上,并将返回值组成一个新的可迭代对象mapped_seq

结构:map(func, *iterables) --> map object
第一个参数是函数名,也可以是lambda表达式,第二个参数是一个可迭代的对象,返回值为map object

import math
map(lambda x:math.pow(x,2),[1,2,3,4,5,6,7])
<map at 0x231ffcec3a0>

返回结果是map object 是可迭代的

list(map(lambda x:math.pow(x,2),[1,2,3,4,5,6,7]))
[1.0, 4.0, 9.0, 16.0, 25.0, 36.0, 49.0]

②标准库functools中的reduce(function,sequence)函数可以接收一个有两个参数的函数function(),以迭代的方式从左到右依次作用到一个序列sequence上实现类huffman树的聚集操作(求和,求连乘积等)

Huffman树聚集

pic

from functools import reduce
reduce(lambda i,j:i+j,range(1,101))
5050

③内置函数filter将一个函数作用到一个序列上,返回该序列中式函数返回值为True的元素组成的filter对象,filter对象也是可迭代的

如:输出从1到1000所有的素数

import math
def is_prime(n):
    if n<2:
        return False
    if n==2:
        return True
    if n%2==0:
        return False
    sqrt_n=math.floor(math.sqrt(n))
    for i in range(3,sqrt_n+1,2):
        if n%i==0:
            return False
    return True
print(list(filter(is_prime,range(1,101))),end=" ")
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97] 

④内置函数zip

zip函数像一个拉链,把两个序列连接返回一个zip对象,可迭代.其元素是两个序列元素组成的元组

list(zip(range(10),'abcdefghij'))
[(0, 'a'),
 (1, 'b'),
 (2, 'c'),
 (3, 'd'),
 (4, 'e'),
 (5, 'f'),
 (6, 'g'),
 (7, 'h'),
 (8, 'i'),
 (9, 'j')]

面对对象设计

类的定义和实例化

①结构

class 类名:
    类成员

关键字为class,类名首字母要大写,如果是自定义类的派生类,则需要用类名+(object)形式.类中的方法和属性不需要使用Pascal法则命名,即首字母不用大写

例:定义Sheep类,内部定义一个name变量,一个shout方法,实例化一个对象sheep,调用shout方法,喊出它的name

class Sheep:
    name='Shown'
    def shout(name):
        print('My name is:',name)

sheep=Sheep()
sheep.shout()
My name is: <__main__.Sheep object at 0x000002715D415640>

运行提示<main.Sheep object>很明显这不是想传进去的name,而是实例化的sheep对象

print(sheep)
<__main__.Sheep object at 0x000002713C772BE0>

类中的方法,分类方法和实例方法.类方法作用于类,实例方法作用域实例.python中的实例方法必须用self来做第一个参数

调用类中的全局变量时用self.变量名

class Sheep:
    name='Shown'
    def shout(self):
        print('My name is:',self.name)

sheep=Sheep()
sheep.shout()
My name is: Shown

也可以用类名调用

class Sheep:
    name='Shown'
    def shout(self):
        print('My name is:',Sheep.name)#用Sheep.name
    def run(self):
        self.shout()
        print('I am running')
sheep=Sheep()
sheep.run()
My name is: Shown
I am running

同样的,类中的实例方法互相调用时也需要用self.方法名,但是不能用类名

class Sheep:
    name='Shown'
    def shout(self):
        print('My name is:',self.name)
    def run(self):
        self.shout()
        print('I am running')
sheep=Sheep()
sheep.run()
My name is: Shown
I am running

如果想在实例化的时候对对象赋初值,则会用到构造方法.python中的构造方法叫做初始化方法,用__init__表示.python中的类,通过__new__实例化,通过__init__来初始化

print(dir(sheep),end=" ")
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name', 'run', 'shout'] 

类中带双下划线的方法或属性如__new__叫做魔法方法/属性,它是类中的已经定义好的方法,一般有类自己调用,也可以通过编程调用或者重写.后面的name,run,shout才是自已定义的方法/属性

重写__init__,添加参数,用来实例化的时候赋初值

class Sheep:
    def __init__(self,name):
        self.name=name
    def shout(self):
        print('my name is:',self.name)
sheep=Sheep('Tom')
sheep.shout()
my name is: Tom

这里的self相当于实例后的独有的空间
self{
    name;
    shout()
}
self和类class的关系就相当于

pic

class Panda:
    attr1='Pandas'
    def func1():
        pass
    def func2(self):
        self.attr2='cats'
    def func3(self):
        print(self.attr2)

        a=3
        print(a)
        pass
pan=Panda()
print('class:',[i for i in dir(Panda) if i[0]!='_'])
print('self:',[i for i in dir(pan) if i[0]!='_'])
class: ['attr1', 'func1', 'func2', 'func3']
self: ['attr1', 'func1', 'func2', 'func3']

可以看到class和self共有attr1,func1,func2,func3,也就是说,在没有调用实例化方法时,self中的属性并不会创建

pan.func2()
print('class:',[i for i in dir(Panda) if i[0]!='_'])
print('self:',[i for i in dir(pan) if i[0]!='_'])
class: ['attr1', 'func1', 'func2', 'func3']
self: ['attr1', 'attr2', 'func1', 'func2', 'func3']

调用pan.func2()后,self区创建了attr2

pan.func3()
print('class:',[i for i in dir(Panda) if i[0]!='_'])
print('self:',[i for i in dir(pan) if i[0]!='_'])
cats
3
class: ['attr1', 'func1', 'func2', 'func3']
self: ['attr1', 'attr2', 'func1', 'func2', 'func3']

可以看到,虽然attr2是在func2()中创建的,但在func3()中仍能调用.但是func3()中的局部变量3并不在pan中.

但是不同的实例之间并不能共用self区

class Panda:
    attr1='Pandas'
    def func1():
        pass
    def func2(self):
        self.attr2='cats'
    def func3(self):
        print(self.attr2)

        a=3
        print(a)
        pass
pan=Panda()
pan1=Panda()
pan.func2()
pan1.func2()
#pan修改attr2不影响pan1
pan.attr2='dogs'
print('pan1.attr2:',pan1.attr2)
pan1.attr2: cats

所以不同实例之间的关系是这样的

如果形参,self变量,类变量名字相同就这样区分

class Panda:
    name='Aa'
    def func(self):
        self.name='Bb'
        name='Cc'
        print(Panda.name)
        print(self.name)
        print(name)
pan=Panda()
pan.func()
print('class:',[i for i in dir(Panda) if i[0]!='_'])
print('self:',[i for i in dir(pan) if i[0]!='_'])
Aa
Bb
Cc
class: ['func', 'name']
self: ['func', 'name']

可以看到三个name值不同.而class和self虽然在内部空间存在相同的属性名name,但他们是两个值

再继续看实例调用类变量的情况

class Panda:
    name='Aa'
    def func(self):
        self.name='Bb'
        name='Cc'
pan=Panda()
print(pan.name)
Aa

未调用func(),实例可以访问类变量

pan.func()
print(pan.name)
Bb

调用func()后,self区的name就被覆盖了

但如果是不同的变量名

class Panda:
    cname='Aa'
    def func(self):
        self.name='Bb'
        name='Cc'
pan=Panda()
print(pan.cname)
pan.func()
print(pan.cname)
print('self:',[i for i in dir(pan) if i[0]!='_'])
Aa
Aa
self: ['cname', 'func', 'name']

就不会覆盖,self此时既有cname,又有name.所以如果类属性和实例属性名字相同,调用函数后,就不能再通过实例访问类属性

sum up:
类中的变量分类变量(class),实例变量(self)和局部变量
类变量直接定义在类中,可以被类名和实例化的对象调用
实例变量定义在方法中,且由self修饰,只有在调用方法时才创建,能被所有实例调用,不能通过类名访问
如果类变量和实例变量名相同,实例调用函数后,会覆盖
局部变量也定义在函数中,使用后销毁,并不占用实例空间

python中的self就是java中的this,唯一区别就是self必须是实例方法的参数的第一个.其实,self只是规定了第一个参数的位置,命名什么都行,也可以用this

class Sheep:
    def __init__(this,name):
        this.name=name
    def shout(this):
        print('my name is:',this.name)
sheep=Sheep('Tom')
sheep.shout()
my name is: Tom

②python类型是动态性的,可以动态为自定义类及对象改变为新的属性和行为,俗称混入(mixin)机制

a=1
print(type(a))
a='hello'
print(type(a))
<class 'int'>
<class 'str'>

但是实际a的引用地址已经发生了改变

a=1
print(id(a))
a='hello'
print(id(a))
2734448994608
2734528578672

利用这个机制,就可以给已经创建好实例,在不修改类,不重新实例化的前提下添加新属性

class Sheep:
    name=''
    def shout():
        pass
shp=Sheep()
print('shp:',[i for i in dir(shp) if i[0]!='_'])
shp.age=12
print('shp:',[i for i in dir(shp) if i[0]!='_'])
shp: ['name', 'shout']
shp: ['age', 'name', 'shout']

而且也可以给类添加新属性

Sheep.type='sheep'
print('Sheep:',[i for i in dir(Sheep) if i[0]!='_'])
Sheep: ['name', 'shout', 'type']

并且,再新的实例也会有type属性

shp1=Sheep()
print('shp2:',[i for i in dir(shp1) if i[0]!='_'])
shp2: ['name', 'shout', 'type']

还有方法也可以添加,但是需要导入type库

import types
def setSpeed(self,s):
    self.speed=s
shp1.setSpeed=types.MethodType(setSpeed,shp1)
#绑定后,实例不但有了setSpeed方法,而且有了speed属性
shp1.setSpeed(5)
print(shp1.speed)
5

③私有不私有特点:

*XXX:一个下划线开始,表示受保护的成员,不能用from .. import导入
XXX*:系统定义的特殊成员,如__init_
__xxx:私有成员,只有类对象自己能访问,子对象不能直接访问.但在对象外部可以通过'对象名._类名__xxx'来访问,所以python中的私有并不是真正的私有

方法

python中的方法分为:实例方法,类方法,静态方法

实例方法第一个参数名为self
类方法第一个形参为cls
静态方法没有规定必须的参数

类方法用@classmethod修饰,静态方法用@staticmethod修饰

python中的静态方法不能使用类或实例中的任何属性和方法,相当于一个独立的空间,常作为工具方法使用.python中的类方法更类似于其他语言的静态方法.

共同点:
类方法和静态方法不能直接访问属于对象的成员
类方法和静态方法都可以用对象或类名来调用

class Cat:
    @classmethod
    def setName(cls,name='Tom'):
        cls.name=name
cat=Cat()
cat1=Cat()
cat.setName('Jerry')
print(cat1.name)
print (Cat.name)
Jerry
Jerry

如上,python中的类方法的不同实例是共用空间的

python的静态方法是一个独立的空间,一般用于和类对象以及实例对象无关的代码。

class Game():
    @staticmethod
    def menu():
        print('开始游戏')
        print('设置')
        print('退出游戏')
    def func1():
        pass
game=Game()
game.menu()
开始游戏
设置
退出游戏

属性
class Sheep:
    def __init__(self,name):
        self.__name=name
    def name(self):
        return self.__name
sheep=Sheep('Shown')
print(sheep.name())
print(sheep.__name)
Shown



---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

c:\Users\Tenerome\Desktop\python\lesson.ipynb Cell 73 in <cell line: 8>()
      <a href='vscode-notebook-cell:/c%3A/Users/Tenerome/Desktop/python/lesson.ipynb#Y134sZmlsZQ%3D%3D?line=5'>6</a> sheep=Sheep('Shown')
      <a href='vscode-notebook-cell:/c%3A/Users/Tenerome/Desktop/python/lesson.ipynb#Y134sZmlsZQ%3D%3D?line=6'>7</a> print(sheep.name())
----> <a href='vscode-notebook-cell:/c%3A/Users/Tenerome/Desktop/python/lesson.ipynb#Y134sZmlsZQ%3D%3D?line=7'>8</a> print(sheep.__name)


AttributeError: 'Sheep' object has no attribute '__name'

想得到sefl.__name私有变量,只能通过函数name的返回值(或用类名+私有变量名),python中的@property装饰器,用它装饰的方法可以对类的私有变量进行读写操作,将来可以通过方法名,不需要加()来对属性读写

class Sheep:
    def __init__(self,name):
        self.__name=name
    @property
    def name(self):
        return self.__name
sheep=Sheep('Shown')
print(sheep.name)
Shown

上面是只读的例子,下面看可读可写的

class Sheep:
    def __init__(self,name):
        self.__name=name
    def __get(self):
        return self.__name
    def __set(self,value):
        self.__name=value
    name=property(__get,__set)
sheep=Sheep('Shown')
print(sheep.name)
sheep.name='Tom'
print(sheep.name)
Shown
Tom

上面是第一种形式,除了getter和setter,还有del

'''class C(object):
    def getx(self): return self._x
    def setx(self, value): self._x = value
    def delx(self): del self._x  
    x = property(getx, setx, delx, "I'm the 'x' property.")'''

如果不定义del的话是不能直接删除的

class Sheep:
    def __init__(self,name):
        self.__name=name
    def __get(self):
        return self.__name
    def __set(self,value):
        self.__name=value
    def __del(self):
        del self.__name
    name=property(__get,__set,__del)

另一种形式:

'''class C(object):
    @property def x(self):
        "I am the 'x' property." return self._x
    @x.setter def x(self, value):
        self._x = value
    @x.deleter def x(self):
        del self._x'''
class Sheep:
    @property 
    def name(self):
        return self.__name
    @name.setter
    def name(self,name):
        self.__name=name
    @name.deleter
    def name(self):
        del self.__name
sheep=Sheep()
sheep.name='Shawn'
print(sheep.name)
# del sheep.name
# print(sheep.name)
Shawn
析构方法

实例化出来的对象都是有声明周期的,当声明周期结束时,会自动调用析构函数,默认无动作.可以在析构函数中自定义语句.析构函数用__func__表示

#在jupyter 中会直接结束对象的声明周期,在py文件中运行这段代码
class Dog:
    def __eat(self):
        print('i am going to eat')
    def can_bite(self,condition):
        if condition==1:
            self.__eat()
        else:
            return "I can't eat"
    def __del__(self):
        print('Over')
dog =Dog()
con=int(input('input one number:'))
dog.can_bite(con)
del(dog)
i am going to eat
Over
继承和多态

①继承:派生类继承基类的属性和方法.

python中的派生类用class 派生类名(基类名):来定义

class A:
    def hello(self):
        print('hello')
class B(A):
    pass
b=B()
b.hello()
hello

如果要在派生类中调用基类的方法,可以使用内置函数super().方法名或者通过基类名.方法名()来调用.私有方法在派生类中不能直接访问

class A:
    def __init__(self):
        __name='shawn'
        self.age=12
    def hello(self):
        print('hello')
class B(A):
    def hi(self):
        super().hello()
b=B()
b.hi()
print(b.age)
print(b.__name)
hello
12



---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

c:\Users\Tenerome\Desktop\python\lesson.ipynb Cell 93 in <cell line: 13>()
     <a href='vscode-notebook-cell:/c%3A/Users/Tenerome/Desktop/python/lesson.ipynb#Y160sZmlsZQ%3D%3D?line=10'>11</a> b.hi()
     <a href='vscode-notebook-cell:/c%3A/Users/Tenerome/Desktop/python/lesson.ipynb#Y160sZmlsZQ%3D%3D?line=11'>12</a> print(b.age)
---> <a href='vscode-notebook-cell:/c%3A/Users/Tenerome/Desktop/python/lesson.ipynb#Y160sZmlsZQ%3D%3D?line=12'>13</a> print(b.__name)


AttributeError: 'B' object has no attribute '__name'

python也支持多继承(C++也支持,java不支持)

②多态(重载)

多态:指基类的同一个方法在不同派生类对象中具有不同的表现和行为.

class Animal:
    def eat(self):
        print('吃')
    def run(self):
        print('跑')

class Dog(Animal):
    def run(self):   #子类重写父类方法
        print('用四个腿跑')#如果想继续调用父类的方法,可以使用super().方法()

dog=Dog()
dog.run()
用四个腿跑

文本

文本文件操作

对文本文件操作,用with open() as f. open是python的内置函数,有三个参数open(filename,mode,encoding),mode是操作模式,有读,写,读写三种.

with open('1.txt','r') as f:
    print(f.read())
Hello world
Nice to meet you

'r':读模式,read()函数,读取文件内容,返回一个str

'w':写模式

'r+'或'w+':读写,不能用rw

'a':追加

with open('1.txt','r+') as f:
    f.write('哈尔滨商业大学')
    print(f.read())
print(f.read())
#不能同时读写?
文件的补充

with open('1.txt','r/w') as f:

这句执行后,r模式会把游标移动到最前面,w模式会清空内容

如果文件不存在,r模式会报错.w模式会自动创建新文件

f.read()会从当前游标位置读取到文档end

f.write()会从当前位置,向后写

①r模式,游标在最前面,先写后读,会覆盖前面的字符,原文档:
pic

r+模式,先写后读

with open('1.txt','r+') as f:
    f.write('Hello')
    print(f.read())
6789

f.write()从最前面开始覆盖写,游标停止在o后,开始读,所以读到的是6789

pic

r+模式,先读后写

with open('1.txt','r+') as f:
   print(f.read())
   f.write('nnnn')
Hello6789

r+模式,开始游标在head,读所有的字符,读完游标在最后,写的内容追加到end
pic

w+模式,先把内容清空

with open('1.txt','w+') as f:
    pass

pic

先写后读

with open('1.txt','w+') as f:
    f.write('MMMM')
    print(f.read())

pic

能写进去,但写完之后游标在end,自然就读取不到,想要读内容,需要用f.seek()移动游标

with open('1.txt','w+') as f:
    f.write('MMMM')
    f.seek(0)
    print(f.read())
MMMM

w+模式,先读后写

with open('1.txt','w+') as f:
   print(f.read())
   f.write('nnnn')

pic

w+模式先清空,所以什么都读不到,然后把内容写进去

a+模式打开时游标默认也在末尾,且文件不存在也新建

二进制文件操作

使用pickle库序列化对象,就是把二进制数据存储在磁盘上

import pickle
i=133000
a=99.23
s='Hello'
lst=[[1,2,3],[4,5,6]]
tu=(2,3,6)
coll={2,4,7}
dic={'a':'apple','b':'banana'}
data=[i,a,s,lst,tu,coll,dic]

想把这些数据存下来

with open('sample.dat','wb') as f:
    try:
        pickle.dump(len(data),f)
        for item in data:
            pickle.dump(item,f)
    except:
        print('写文件异常')

读写二进制文件,就是在w/r/a后面加b,pickle.dump(obj,file_writeable),dump()函数可以把任意对象写入一个可写的文件对象中

使用pickle库反序列化对象

with open('sample.dat','rb') as f:
    n=pickle.load(f)
    for i in range(n):
        x=pickle.load(f)
        print(x)
        print(type(x))
133000
<class 'int'>
99.23
<class 'float'>
Hello
<class 'str'>
[[1, 2, 3], [4, 5, 6]]
<class 'list'>
(2, 3, 6)
<class 'tuple'>
{2, 4, 7}
<class 'set'>
{'a': 'apple', 'b': 'banana'}
<class 'dict'>

使用pickle.load()读取二进制文件,返回any,根据不同的类型,x的类型动态变化

OS和OS.path模块

open()用来读写单个文件,如果想对目录中的文件读写,需要OS,OS.path库

OS库:

getcwd(): 获取当前目录的path

mkdir(): 创建目录

listdir(path): 返回path目录下的文件和子目录列表

walk(top,topdown=True,onerror=None): 遍历目录树,就是所有目录及其子目录的所有文件

remove(path):删除指定文件,要求用户拥有删除文件的权限,并且文件没有只读或其他特殊属性

rename(src,dst):重命名文件或目录,可以实现文件的移动

startfile(filepath[,operation] ):使用关联的应用程序打开指定文件或启动指定应用程序

OS.path库:

os.path

import os
import os.path
for i in os.listdir():
    if os.path.isfile(i) and i.endswith('.py'):
        print(i)
test.py

os.path.isfile(path):判断是否为文件,返回bool

S.endswith('suffix'):Return True if S ends with the specified suffix

os.path.exist(path):判断当前路径是否存在指定的目录或文件

os.path.dirname('1.txt'):获取文件的目录部分,是相对路径

os.path.splittext('1.png'):分隔文件名和扩展名,运行结果:('1','png')

os.path.join(path,*path),连接两个或多个path

posted @ 2022-11-07 12:22  Tenerome  阅读(183)  评论(0)    收藏  举报