Python基础手记

  1. 又一个非常方便的Python语法特性

class Product:
    def __init__(self, value):
        self.price = value

    @property
    def price(self):
        return self.__price

    @price.setter
    def price(self, value):
        if value < 0:
            raise ValueError
        self.__price = value

我们使用@property修饰方法,此时会把方法直接变成同名属性。当我们获取属性的值时,实际上就是调用的此方法。

此时,本身又自动创建了另一个装饰器,负责把一个方法变成属性赋值,即:price的setter方法。于是,修饰的其实是,当我们给price赋值时,实际上就是调用的此方法。此时,price对外表现得就像一个普通的attribute

  1. 继承
class Animal:
    def __init__(self):
        self.age = 1

    def eat(self):
        print('eat')


class Mammal(Animal):
    def walk(self):
        print('walk')


m = Mammal()
print(m.age) # 1
m.eat() # eat
print(isinstance(m, object))  # True
print(issubclass(Mammal, Animal))  # True

所有的类都直接或者间接继承自 object 类

除此以外,还可以非常方便地通过继承扩展内置类型(比如str,list等)

  1. 继承中的构造器

    不同于Java或者C++的构造器机制(类同名,默认构造器,从父到子),Python中的构造器只有一个名字__init__,这也造成了一个神奇的结果:Python的构造器是可以 覆盖 的,而且子类的实例化可以完全不执行父类的构造方法。如果需要在子类的构造器中执行父类的构造器,需要 显式指明 :

def __init__(self):
        super().__init__()
        self.weight = 2

另外,如果子类没有自己的构造器,则只会执行父类的构造器,也就是说不存在所谓的 默认构造器 。

  1. Python中的抽象类和抽象方法

    机制大同小异,不再赘述:

from abc import ABC, abstractmethod


class Stream(ABC):  # 抽象类

    @abstractmethod
    def read(self):  # 抽象方法
        pass


class MemoryStream(Stream):

    def read(self):
        print('read')


stream = MemoryStream()

值得注意的是,Python并不支持函数重载,这也意味着所谓的重写(覆盖)的函数签名不包括形参,而只是 函数名 。

  1. 多态

    由于Python中不存在所谓的上转型对象,所以实现多态的方式也有所变化。

    可以简单的通过一个函数实现

def operate(control):
    control.do_something()

显然,只要对象存在该方法,即使不在同一继承体系也可以成功执行,即“is-a“变成了“like-a"

  1. 纯数据类
from collections import namedtuple

Point = namedtuple("Point", ['x', 'y'])

p1 = Point(x=1, y=2)
p2 = Point(x=1, y=2)
print(p1 == p2)

我们不必在重写魔法方法来定义比较规则,同时这种方法创建的数据类是不可变的

  1. 引入模块的方式
from sales import calc_shipping # 此时calc_shipping就好像在该文件定义一样直接使用
import sales # 此时sales可以看作一个对象,通过sale.doSomething访问模块成员
  1. Python编译 
    一旦我在main里import了app并运行,就会产生如图的文件 
    [站外图片上传中...(image-14bf3c-1553528837227)] 
    实际上,pycache里存放了app的编译结果作为缓存,加快下次引入app模块的速度。 
    同时,Python不会编译作为入口的文件(此处是main.py)
  2. 模块路径 
    就如同Java的类路径,Python也有模块路径用于在程序import时搜寻相应的模块,当前目录就是其中之一。
import sys
print(sys.path) # 打印所有模块路径
  1. 包(package)

    包简单来说就是模块的集合,对应到文件层面包就是一个 目录 ,模块就是一个 py文件 。

    新建一个目录,并在其中新建一个名为 __init__.py 的文件,这个目录就变成了一个包,同时包还可以有子包,同样创建一个子目录和init文件,以此类推。

    那么如何import同级子包中的模块呢?

from 最顶级包.目标包 import 目标模块
from ..目标包 import 目标模块 # 两个点表示上级目录(包)

两种方法分别对应绝对和相对寻址

import app

print(dir(app))  #返回scope的所有属性名
print(app.__name__) # 模块名
print(app.__file__)  # 路径
print(app.__package__)

值得注意的是,如果直接执行某个模块,模块名(__name__)总会是 __main__ ,所以也就有了常见的:

if __name__ == "__main__":
    pass

猜你喜欢

转载自blog.csdn.net/zhoulei124/article/details/89022067
今日推荐