Python的进阶话题

本文深入探讨Python编程的高级话题,包括所有内容都是对象的概念,详细解释了不可变对象的工作原理;介绍闭包(Closure)和生成器(Generator)的概念;讨论了函数参数的不同传递方式及with语句的使用;阐述了Python的继承机制,特别是多继承的特点;最后,重点讲解了装饰器(Decorator)的实现和作用,如何处理带参数的函数装饰器,并强调其在减少代码冗余中的价值。

1,Python中的一切都是对象。

string是对象,list是对象,函数是对象,甚至module也是对象。Python中的一切都是对象,都可以被赋值给一个变量或被当作参数传递给函数。

任何可以写在等号右侧的都是对象。

def say_hi():
    print("Hello!")

hi = say_hi # 将函数直接赋给另一个变量。
hi()

string,integer和tuple是不可更改(immutable)的。例如 a = "string",当给a赋新值时,例如a = "string1"时,将"string1"放入新的内存空间,并将a指向新的内存空间。旧的内存空间在不久后会被回收掉。如果是可更改的对象,则直接将内存空间存储的值改成新值就可以了。

2,Closure

def outer_f(x):
    def inner_f(y):
        return x + y
    return inner_f # 注意这里只写函数名,不能带(),因为不是调用,而且把函数的identifier送出去。

test = outer_f(3) # closure的意思是,将outer_f(3)的逻辑和状态作为一个整体封装起来,因此称为closure。
print(test(5))

3,Generator

def f(): # 这个函数称为一个generator。
    for i in range(10):
        yield i # yield 关键字返回i,而不是集合。

for j in f(): #当使用generator时,generator一次只返回一个值,而不是一个可遍历的对象。
    print(j)

# generator的作用是提高效率。例如我们需要使用generator产生无限多元素的时候(例如传感器隔几秒产生一个数据,一直持续)。用普通for产生集合的话,程序直接就死了。而generator是需要一个产生一个,因此不会有问题。
(expr(item) for item in iterable) # generator comprehension

for j in ( i for i in range(0,10,2)):
    print(j)

4, 不同的函数参数传递方式。

# 1,使用位置传参或使用关键字传参。
def f1(name, age): # 普通函数的写法,通过参数传递的位置确认对应关系。
    pass

f1("yan", 30)
-------------------------

def f1(name, age):
    pass

f1(age = 30, name = "yan") # 使用关键字传递参数,则不再受位置影响。

-------------------------
def f1(name, age, gender):
    pass

f1("yan", age = 30, gender = "F") # 但是位置传参必须在关键字传参前面。

# 2,给参数设置默认值
def f1(name, age = 0):
    pass

f1("yan")

# 3,使用*args可以让函数接受个数不固定的位置参数。
def f1(*args): 
    print(args) # 这里打印出来可知是一个tuple,且为(1,2,3)

f1(1,2,3)


# 4,使用**kwargs可以让函数接受个数不固定的关键字参数。
def f3(*args, **kwargs): # 注意*必须在**之前,否则会报错。
    print(args) # 这里是一个tuple
    print(kwargs) # 这里是一个dictionary

f1(1,2,3,name='tom',age=10) # 也是必须位置参数在前。

5,with statement

在Python基础中提到用with open来操作文件:

with open(os.getcwd() + '/hw_25000.csv') as sample_file:
    sample_content = sample_file.read() # return content of the file as a long string.
	sample_content = sample_file.readlines() # 这里并不是循环打印每行,而是返回list of string from the file.

with不仅可以和open搭配使用,实际上只要是实现了__enter__和__exit__方法的类,都可以和with statement搭配:

class Resource:
    def __enter__(self):
        print("enter...")
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("exiting...")
        
with Resource() as r:
    print("running") # 由打印结果可以看出,首先调用了__enter__,然后是print("running"),最后是__exit__。
f = open(os.getcwd() + '/main.py') # 对于open函数,在IDE里可以清晰地看到f实现了__enter__和__exit__方法。

6,继承

Python是允许多继承的,即子类可以同时继承多个父类。但Java就不允许这么做。

class Person:
    def __init__(self, name, age):
        self._name = name
        self._age = age

    def say_my_name(self):
        print(f"Hi, my name is {self._name}")

    def say_my_age(self):
        print(f"Hi, my age is {self._age}")

    def self_introduction(self):
        print(f"Hi, my name is {self._name}, my age is {self._age}.")

class Student(Person): # Person是父类
    def __init__(self, name, age, grade):
        Person.__init__(self, name, age) # 调用父类的构造函数
        self._grade = grade

    def say_my_grade(self): # 子类自己实现的函数
        print(f"Hi, I am {self._grade} grade")

    def self_introduction(self): # 子类覆盖父类的函数
        print(f"Hi, my name is {self._name}, my age is {self._age} and I am {self._grade} grade.")

i = Student("luyan", 12, 6)
i.say_my_name()
i.say_my_grade()
i.self_introduction()

7,Decorator 参考文档

decorator比较复杂,看原文更利于理解,因此这里只记一下decorator的样子。

def make_pretty(func): # decorator是一个函数,传入参数也是函数。 目的是“装饰”传入的函数。
    def inner():
        print("I got decorated") # 这是要添加的“装饰”
        func() # 然后执行传入的函数
    return inner

@make_pretty
def ordinary():
    print("I am ordinary")

ordinary()
-------------------
I got decorated # 首先执行“装饰”的部分
I am ordinary # 然后执行函数本身

以上就实现了decorator,但它的问题是:当ordinary()需要传递参数时怎么办?原文有答案。

decorator的作用是减少代码冗余。例如这里需要调用三个方法,需要在每次调用前记一行log,调用结束后再记一行log。与其在每次调用前后打log,不如使用decorator更为简洁高效。

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值