python进阶内容

目录

Python中is和==的区别?

赋值,浅拷贝和深拷贝的区别

Python基本数据类型中哪些可变,哪些是不可变

python的内存管理机制的原理

面向对象

继承

多态

封装

时间和日期

魔法方法

类方法

类方法和实例方法的区别:

闭包

生成器


以下的内容是我整理的一些python的内容,有的不一定简单,有的也不一定难,可能中间会有些别的博主的内容穿插,但是我忘记了是哪些,所以以此先声明,并不是所有的内容都为原创。

Python中is和==的区别?

is判断的是a对象是否就是b对象,是通过id 来判断的。

==判断的是a对象的值是否和b对象的值相等,是通过value来判断的。

赋值,浅拷贝和深拷贝的区别

  • 赋值:

赋值操作(包括对象作为参数、返回值)不会开辟新的内存空间,它只是复制了对象的引用。

  • 浅拷贝:

浅拷贝会创建新对象,其内容非原对象本身的引用,而是原对象内第一层对象的引用。

浅拷贝有三种形式:切片操作、工厂函数、copy模块中的copy函数。

所谓工厂函数,就是指这些内建函数都是类对象,当你调用他们时,实际上是创建了一个类实例”。意思就是当我调用这个函数,实际上是先利用类创建了一个对象,然后返回这个对象。

比如上述的列表a;

切片操作: b = a[:]或者b = [x for x in a];

工厂函数: b = list(a);

copy函数: b =copy.copy(a);

浅拷贝产生的列表b不再是列表a了,使用is 判断可以发现他们不是同一个对象,使用id查看,他们也不指向同一片内存空间。但是当我们使用id(x) for x in a和id(x) for x in b来查看a和b中元素的地址时,可以看到二者包含的元素的地址是相同的。

在这种情况下,列表a和b是不同的对象,修改列表b理论上不会影响到列表a。

但是要注意的是,浅拷贝之所以称之为浅拷贝,是它仅仅只拷贝了一层,在列表a中有一个嵌套的 list,如果我们修改了它,情况就不一样了。

比如: a[3].append(java')。查看列表b,会发现列表b也发生了变化,这是因为,我们修改了嵌套的 list,修改外层元素,会修改它的引用,让它们指向别的位置,修改嵌套列表中的元素,列表的地址并未发生变化,指向的都是用一个位置。

  • 深拷贝:

深拷贝只有一种形式,copy模块中的deepcopy()函数。

深拷贝和浅拷贝对应,深拷贝拷贝了对象的所有元素,包括多层嵌套的元素。因此,它的时间和空间开销要高。

同样的对列表a ,如果使用b =copy.deepcopy(a),再修改列表b将不会影响到列表a,即使嵌套的列表具有更深的层次,也不会产生任何影响,因为深拷贝拷贝出来的对象根本就是一个全新的对象,不再与原对象有任何的关联。

注!!对于非容器类型,如数字、字符,以及其他的"原子"类型,没有拷贝一说,产生的都是原对象的引用。如果元组变量值包含原子类型对象,即使采用了深拷贝,也只能得到浅拷贝。

Python基本数据类型中哪些可变,哪些是不可变

python可变数据类型:列表list[ ]、字典dict{ }

python不可变数据类型:整型int、字符串str' '、元组tuple()

python的内存管理机制的原理

1. 引用计数

当一个python对象被引用时 其引用计数增加 1 ; 当其不再被变量引用时 引用计数减 1 ; 当对象引用计数等于 0 时, 对象被删除(引用计数是一种非常高效的内存管理机制)。

2. 垃圾回收

垃圾回收机制: ① 引用计数 , ②标记清除 , ③分带回收

引用计数 :

引用计数也是一种垃圾收集机制, 而且也是一种最直观, 最简单的垃圾收集技术.当python某个对象的引用计数降为 0 时, 说明没有任何引用指向该对象, 该对象就成为要被回收的垃圾了.(如果出现循环引用的话, 引用计数机制就不再起作用了)

标记清除 :

如果两个对象的引用计数都为 1 , 但是仅仅存在他们之间的循环引用,那么这两个对象都是需要被回收的, 也就是说 它们的引用计数虽然表现为非 0 , 但实际上有效的引用计数为 0 ,.所以先将循环引用摘掉, 就会得出这两个对象的有效计数.循环引用的基本形式如下:

a =[]

b=a

a.append(b)

b.append(a)

分带回收 :

从前面“标记-清除”这样的垃圾收集机制来看,这种垃圾收集机制所带来的额外操作实际上与系统中总的内存块的数量是相关的,当需要回收的内存块越多时,垃圾检测带来的额外操作就越多,而垃圾回收带来的额外操作就越少;反之,当需要回收的内存块越少时,垃圾检测就将比垃圾回收带来更少的额外操作。

3.内存池

内存池机制: python 中分为大内存和小内存: 256k为界限

大内存使用malloc 进行分配

小内存使用内存池是进行分配

python的内存池金字塔:

第3层: 最上层, 用户对python对象的直接操作

第1层和第2层: 内存池, 有python 的 接口函数 PyMen_Malloc 实现, 若请求分配的内存在1 - 256字节之间就使用内存池进行分配, 调用malloc 函数分配内存, 但是每次只会分配 256 k 的内存. 不会调用free 函数释放内层. 将该内存块留在内存池中便下次使用

第 0 层: 大内存 . 若请求分配的内存大于 256 k , malloc函数分配, free函数释放内存

第 - 1 -2 层: 操作系统进行操作

面向对象

继承

单继承:

class a(b): pass

多继承:

# 三个方法里应该都要有构造方法__init__,但是我懒得写 

class b: 
    def hello(self): 
        print('你真棒') 

class c: 
    def hello(self): 
        print('你真厉害') 
    
class a(b,c): 
    pass

结论:一个类继承多个父类会优先继承第一个类的数学和方法(就近原则),即调用a类里的hello方法的话,会先调用b里的hello方法(你真棒)

# 三个方法里应该都要有构造方法__init__,但是我懒得写 
class b: 
    def hello(self): 
        print('你真棒') 

class c: 
    def hello(self): 
        print('你真厉害') 

class a(b,c): 
    def hello(self): 
        print('我可真厉害')

超继承就是继承父类的方法的同时也拥有自己的方法

重写:子类重写父类的方法

重载:定义相同的方法名、参数不同

多态

多态:不明显 不需要继承

指的是同一类型的事物,有不同的形态

传入不同的对象,产生不同的结果 动物都会吃 吃的东西不一样

class Pig: 
    def eat(self): 
        print('猪吃饭') 

class Cat: 
    def eat(self): 
        print('猫吃猫粮') 

class Dog: 
    def eat(self): 
        print('狗吃狗粮') # 传入不同对象 
    def eat(a): 
        a.eat() 
        
p=Pig() 
c=Cat() 
d=Dog() 
eat(p)# 猪吃饭 
eat(c)# 猫吃猫粮 
eat(d)# 狗吃狗粮

封装

封装就不用多讲了吧。。。。不会的可以去网上查查

时间和日期

import calendar
import time

# 输出6月的日历
cal=calendar.month(2022,6)
print(cal)

# 22年的年历
year=calendar.calendar(2022)
print(year)

# 时间戳:从1970年1月1日0点0分0秒时间-现在的秒数
print('当前时间戳:', time.time())

# 时间元组  元组(年月日时分秒 一周的第几日 0-60是星期一一年的第几天夏令时)#
t = (2022, 6, 16, 22, 19, 21, 72, 6)
print(t)
# 时间戳转为时间元组
print('时间戳转为时间元组', time.localtime(time.time()))

# 时间元组转为日期time.asctime
print('英文的日期', time.asctime(time.localtime(time.time())))

# 日期格式百度%Y %m %d这个用的多点
print(time.strftime('%Y/%m-%d %H:%M:%S'))

魔法方法

# 魔法
# 用init初始化函数  作用 只要创建类对象,就会执行这个init
# __str__对象描述方法,只要定义了__str__方法,对象就会打印这个方法中return
# __del__销毁对象,不管写不写这个del函数,都会销毁
# __new__ 创建类的对象

类方法

类方法和实例方法的区别:

1、类方法是属于整个类,而不属于某个对象。

2、类方法只能访问类成员变量,不能访问实例变量;实例方法可以访问类成员变量和实例变量。

3、类方法的调用可以通过类名,实例方法只能通过对象。

4、类方法只能访问类方法,实例方法可以访问类方法和实例方法。

5、类方法不能被覆盖,实例方法可以被覆盖。

# 类方法 实例方法 静态方法:
# 实例方法 类中的函数带有self
# 类方法:需要用到@classmethod装饰,参数命名cls
# 静态方法:需要用到@staticmethod装饰,参数没有self也没有cls  参数

class Stu:
    school = '幸福学院'

    def __init__(self, name, age):
        self.name = name
        self.age = age

    # 实例方法
    def play_ball(self):
        print(f'{self.name}打篮球')

    # 类方法
    @classmethod
    def sport(cls):
        print(f'{cls.school}的同学都喜欢打羽毛球')

    # 静态方法内部里面没有用到类相关的内容,可以把这个函数定位静态方法
    # 定义成静态方法可以不用对象.方法名。可以类.方法名
    # 静态方法要求,你想要把你的普通方法定义成静态方法,要求你的这个方法,不要去引用到外部的东西
    @staticmethod
    def clean():
        print('打扫卫生')


stu1 = Stu('cxk', 18)
stu1.play_ball()
Stu.play_ball(stu1)

stu1 = Stu('cxk', 18)
stu1.sport()
Stu.sport()

Stu.clean()
# 实例方法:对象名.方法名()  类.方法名(对象名)
# 类方法:对象名.方法名()   类.方法名  你的整个类都可以拥有的一个方法,可以设计成类方法
# 静态方法:对象名.方法名()  类.方法名  不会访问类的任何属性或其他方法,可以设计成静态方法

闭包

# 闭包:
# 形成条件
# 1.实现函数嵌套
# 2.内部函数使用外部函数的变量
# 3.外部函数返回内部函数名字,不要加括号

# 简单写个闭包
def test01(a):
    b = 1

    def test02():
        result=a+b
        return result

    return test02

生成器

# 生成器也就是一个特殊的迭代器,使用yield的函数就被称为生成器,不是一个普通的函数了
def gen():
    yield


print(gen())


# 第一种用yield 生成器
# 5
def gen(n):
    # 0,1,2,3,4
    for i in range(n):
        # 每次遇到yield时候函数暂停并报错当前的运行信息
        yield i * i

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值