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

被折叠的 条评论
为什么被折叠?



