Python高级语法

属性与方法

1、类属性与实例属性

类:模板定义属性和方法的封装
实例:具体的类对象,是类的表现
(1)实例属性会根据实例的不同而不同,类属性由类决定
(2)实例属性通常在构造函数__init__中赋值
(3)类属性属于类,实例属性属于实例。实例确定,实例属性确定。实例可以调用类属性,类不可以调用实例属性(Good.addr报错)

class Good:
	# 类属性
	name = "tea"
	
	def __init__(self, addr):
		# 实例属性
		self.addr = addr
	
g1 = Good("fujian")
g2 = Good("guangdong")

print(g1.addr, g2.addr)

print(Good.name, g1.name)

2、类方法、静态方法、实例方法

类方法:需要第一个参数为cls, 并且使用@classmethod声明
静态方法:需要使用@staticmethod声明
实例方法:需要第一个参数为self
(1)类可以调用 类方法、静态方法
(2)实例可以调用 类方法、静态方法、实例方法

class Good:
	"""
	这是一个商品类
	"""
	def __init__(self, name):
		self.name = name
	
	def getname(self):
		return self.name
	
	@classmethod
	def getinfo(cls):
		print(cls.__doc__)
	
	@staticmethod
	def pprint():
		print("hello world")

	
g1 = Good("tea")
print(g1.getname())
g1.getinfo()
g1.pprint()

3、对比

(1)类属性 类方法属于类,只占一份内存
(2)实例方法 实例方法,浪费内存

4、属性编写

class Good:
    def __init__(self, _name):
        self.name = _name

    @property
    def gname(self):
        return self.name

    @gname.setter
    def gname(self, _name):
        self.name = _name


g1 = Good("tea")
print(g1.name) # tea
print(g1.gname) # tea
g1.gname = "coffee"
print(g1.gname) # coffee

Python是动态语言

1、定义

动态语言:是在运行时可以改变其结构的语言,Python是动态语言,不需要编译,直接由解释器解释执行,效率低下。

2、动态添加

import types


class Good:
    # 通过__slots__限制动态添加内容
    __slots__ = ["name", "addr", "geti"]

    def __init__(self, _addr):
        self.addr = _addr


g1 = Good("fujian")
# 动态添加实例属性
g1.name = "tea"
# 添加类属性
Good.name = "tea"
print(g1.name) # tea


def getinfo(self):
    print(self.addr)


# 动态添加实例方法
g1.geti = types.MethodType(getinfo, g1)

g1.geti() # fujian


@classmethod
def getdoc(cls):
    print(cls.__doc__)

# 添加类方法
Good.getd = getdoc
Good.getd() # None


@staticmethod
def get():
    print("staticmethod")


# 添加静态方法
Good.get = get
Good.get()

# 删除方法
delattr(Good, "get")
# 判断方法是否存在
if hasattr(Good, "get"):
    print("存在get")

生成器

1、什么是生成器

一种边循环边计算的机制,称为生成器:generator

2、生成器的创建

(1)把一个列表生成式的[] 改成()

import sys


# 普通列表生成式
list1 = [x for x in range(100000)]
print(sys.getsizeof(list1))
# 824464

# 使用生成器
list2 = (x for x in range(100000))
print(sys.getsizeof(list2))
# 120

# 得到生成器内容
print(list2.__next__())
# 0
print(next(list2))
# 1

# 遍历生成器
for i in list2:
    print(i)

# 通过异常捕获遍历生成器
while True:
    try:
        print(next(list2))
    except StopIteration as e:
        print(e)
        break

(2)使用函数来创建

def fun():
    yield 1
    yield 2
    yield 3
    return "hello world"


# 获得生成器内容
print(next(fun()))
# 1

for i in fun():
    print(i)
# 1 2 3

# 获得函数返回值
f = fun()
try:
    print(next(f))
    print(next(f))
    print(next(f))
    print(next(f))
except StopIteration as e:
    print(e)

(3)使用生成器打印斐波那契数列

def fun(num):
    a = 0
    b = 1
    count = 0
    yield a
    yield b
    while count < num:
        a, b = b, a+b
        yield b
        count += 1
    return "hello world"


result = fun(10)
for i in result:
    print(i, end=" ")
# 0 1 1 2 3 5 8 13 21 34 55 89 

3、生成器的特点

(1)节约内存
(2)迭代到下一次的调用时,所使用的参数都是第一次所保留下的,即在整个所有函数调用的参数都是第一次用时保留的,而不是新创建的。

迭代器

1、可迭代对象

iterable:可以用于for循环的对象。

2、迭代器

iterator:可以被next()调用并不断返回下一个值的对象。

from collections.abc import Iterable, Iterator

list1 = [1, 2, 3]
print(isinstance(list1, Iterable))
# True
print(isinstance(list1, Iterator))
# False

list2 = (x for x in range(10))
print(isinstance(list2, Iterable))
# True
print(isinstance(list2, Iterator))
# True

3、iter()函数

# iter()函数可以将可迭代对象转换为迭代器
list1 = iter(list1)
print(next(list1), isinstance(list1, Iterator))
# 1 True

闭包

1、什么是闭包

函数的内部再声明一个函数
外部函数返回内部函数的引用
内部函数可以访问外部函数局部变量

2、例子

def fun1(a):
    def fun2(b):
        nonlocal a
        return a + b
    return fun2


f = fun1(10)
print(f(20))
# 30

装饰器

作用:在不改变原函数的情况下给函数增加功能。

1、使用装饰器

"""
解释器解释到有装饰器的函数:会改变函数结构
把函数作为参数传给装饰器,并且执行装饰器的返回值(装饰器返回的为内部函数)
把装饰器内部函数赋给被装饰函数
"""


def check(fun):
    print("最先执行")
    
    def ck(*args):
        # print(type(fun), fun.__name__)
        # <class 'function'> selectgoods
        # 在查询商品之前需要输入权限验证
        user = input("请输入用户名: ")
        if user == "liuhaoran":
            fun(*args)
        else:
            print("无权限")
    return ck


@check
def showlist():
    for i in range(10):
        print(i)


@check
def showdetail(num):
    print("当前为第%s页" % (num))


showlist()
showdetail(10)

深 浅拷贝

1、"="

"""
"=" 是一般意义的复制,相当于引用
内层外层均拷贝引用
"""
list1 = [1, 2, 3, [4, 5]]
list2 = list1
print(list2 is list1)
# True
print(list2[3] is list1[3])
# True
list1.insert(3, 3.5)
print(list1, list2)
# [1, 2, 3, 3.5, [4, 5]] [1, 2, 3, 3.5, [4, 5]]

list1[4].insert(1, 4.5)
print(list1, list2)
# [1, 2, 3, 3.5, [4, 4.5, 5]] [1, 2, 3, 3.5, [4, 4.5, 5]]

2、浅拷贝

"""
浅拷贝
外层拷贝值,内层拷贝引用
"""
import copy

list1 = [1, 2, [3, 4]]
list2 = copy.copy(list1)
print(list1 is list2)
# False
print(list1[2] is list2[2])
# True

list1.insert(2, 2.5)
print(list1, list2)
# [1, 2, 2.5, [3, 4]] [1, 2, [3, 4]]

list1[3].insert(1, 3.5)
print(list1, list2)
# [1, 2, 2.5, [3, 3.5, 4]] [1, 2, [3, 3.5, 4]]

3、深拷贝

"""
深拷贝
外层拷贝值,内层拷贝值
"""

import copy
list1 = [1, 2, 3, [4, 5]]
list2 = copy.deepcopy(list1)
print(list1 is list2)
# False

print(list1[3] is list2[3])
# False

list1.insert(2, 3.5)
print(list1, list2)
# [1, 2, 3.5, 3, [4, 5]] [1, 2, 3, [4, 5]]

list1[4].insert(1, 4.5)
print(list1, list2)
# [1, 2, 3.5, 3, [4, 4.5, 5]] [1, 2, 3, [4, 5]]

元类

1、什么是元类

元类就是用来创建类的东西。

2、使用type创建类

"""
使用type可以动态的创建类
type(类名,由父类名称组成的元组,包含属性的字典)
"""
AI = type("AI", (), {"hp": 100})
print(AI)
# <class '__main__.AI'>
print(AI.__class__)
# <class 'type'>
ai = AI()
print(ai.__class__)
# <class '__main__.AI'>


# 定义普通方法
def speak(self):
    print("hello")


# 定义静态方法
@staticmethod
def attack():
    print("attack")


# 定义类方法
@classmethod
def dead(cls):
    print("dead")


NPC = type("NPC", (AI,), {"canMove": False, "speak": speak, "attack": attack, "dead": dead})
npc = NPC()

npc.speak()
npc.attack()
npc.dead()

3、自定义元类

"""
元类就是用来创建类的东西
使用元类的好处:
拦截类的创建
修改类
返回修改之后的类
"""


# 实现所有的属性均需要以类名开始
def renameattr(classname, parentclass, attrs):
    newattr = {}
    for k, v in attrs.items():
        # print(k, v)
        if not k.startswith("__"):
            k = classname.lower()[0] + "_" + k
            print(k)
            newattr[k] = v
    return type(classname, parentclass, newattr)


class Good(metaclass=renameattr):
    id = None
    name = None


g = Good()
print(hasattr(Good, "name"))
print(hasattr(g, "g_name"))

垃圾回收

python采用引用计数机制为主,标记-清理和分代收集为辅的策略。

1、引用计数

(1)引用计数+1的情况

 对象被创建时,例如a = “hello world”
 对象被copy引用时,例如b = a,此时a引用计数+1
 对象被作为参数,传入到一个函数中时
 对象作为一个子元素,存储到容器中时,例如list = [a, b]

(2)引用计数-1的情况

 对象别名被显示销毁,例如del a
 对象引用被赋予新的对象,例如b = c, 此时b引用计数-1
 一个函数离开他的作用域,例如函数执行完成
 对象所在容器被销毁,或者从容器中删除

优点:简单、直观、实时性
缺点:维护引用计数需要消耗一定的资源、循环应用时,无法回收。

2、标记-清除

a=[1,2]#假设此时a的引用为1
b=[3,4]#假设此时b的引用为1
#循环引用
a.append(b)#b的引用+1=2
b.append(a)//a的引用+1=2

 标记删除第一步: 对执行删除操作后的每个引用-1, 那么a的引用就是0, b的引用为1, 将a放到死亡容器, 将b放到存活容器。
 标记删除第二步: 循环存活容器, 发现b引用a, 复活a: 将a放到存活容器内。
 标记删除第三步: 删除死亡容器内的所有对象。

3、分代收集

(1) 新创建的对象做为0代
(2) 每执行一个【标记-删除】 , 存活的对象代数就+1
(3)代数越高的对象(存活越持久的对象) , 进行【标记-删除】 的时间间隔就越长。 这个间隔, 江湖人称阀值。

4、小整数对象池与intern机制

(1) 小整数[-5, 257): 共用对象, 常驻内存
(2) 单个字符: 共用对象, 常驻内存
(3)单个单词等不可变类型, 默认开启intern机制, 共用对象, 引用计数为0时销毁。

内建函数

1、dir

import dir
print(dir(math))

2、range

a = range(5)
list(a)

3、map

根据提供的函数对指定序列做映射

def fun1(x, y):
	return (x, y)


list1 = [0, 1, 2, 3, 4, 5]
list2 = ["one", "two", "three", "four"]
result = map(fun1, list1, list2)
print(list(result))

# [(0, 'one'), (1, 'two'), (2, 'three'), (3, 'four')]

4、filter

对指定序列执行过滤操作

def fun(x):
    if x >3:
        return True
    else:
        return False

list1 = [1, 2, 3, 4, 5]
result = filter(fun, list1)
print(list(result))

# [4, 5]

5、reduce

对参数序列中元素进行累积

from _functools import reduce

def fun(x, y):
    return x + y

list1 = [1, 2, 3, 4, 5]
result = reduce(fun, list1)
print(result)

# 15

6、sorted

对指定的序列排序

list1 = [1, 3, 5, 7, 2]
result = sorted(list1, reverse=1)
print(result)

# [7, 5, 3, 2, 1]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值