python 学习笔记

类成员

类的成员包括变量(类变量和实例变量),方法(绑定方法,类方法,静态方法)和属性(@property)

私有成员

以双下划线开始的变量,方法和属性被称作私有成员,不能直接被外部调用。并且,私有成员无法被继承

实例变量与类变量

  1. 类体中、所有函数之外:此范围定义的变量,称为类属性或类变量;
  2. 类体中,所有函数内部:以“self.变量名”的方式定义的变量,称为实例属性或实例变量;
  3. 类体中,所有函数内部:以“变量名=变量值”的方式定义的变量,称为局部变量;
  4. 实例和类都能访问类变量,但在给类变量赋值时有所区别:
    • 类调用类变量赋值时,是直接修改了类变量;
    • 实例调用类变量赋值时,是给此实例新建了一个实例变量,并赋值,因此不会影响到类变量的值
  5. 实例变量和类变量可以同名,但这种情况下使用类将无法调用类变量,它会首选实例变量,这也是不推荐“类变量使用对象名调用”的原因;
  6. 对实例中不存在的变量赋值时,会在实例里新建此变量;
  7. 对实例中的变量赋值时,会在实例里新建和此类变量重名的实例变量;

继承

  1. python 是多继承,继承顺序是从下至上,从左往右,如果有第一顺位父类的类变量和方法优先被继承,后续顺位的父类的同名类变量和方法则会再被继承

  2. 多继承中,需要在子类的构造函数中显示的调用多个父类的构造函数,才能继承多个父类的实例变量,但实例变量的继承关系是后续顺位覆盖前面顺位的实例变量,这点和类变量和方法的继承关系不一样

  3. 显示调用父类构造函数有两种方法,只有第一种方法可以调用多继承中的多个父类构造函数

    • 未绑定方法, Parent.__ init __(self)
    • 使用super函数, super(). __ init __()
  4. 多继承中,如果不实现子类的构造函数,默认使用第一顺位父类的构造函数。这时,如果后续顺位的父类构造函数中有入参,在调用继承的后续顺位父类方法时,可能出现找不到某个变量的情况,原因是后续顺位父类没有调用构造函数传参

方法类型

三种方法均可以被类和对象调用,主要是使用场景的不同,根据是否需要self 和 cls参数判断实现哪种类型的方法

绑定方法

普通的类内方法

class A:
    def f0(self):
        pass

类方法

类内方法,不带self 参数,取而代之的是cls参数,并且被 @classmethod 装饰的方法

class A:
    @classmethod
    def f1(cls):
        pass

静态方法

类内方法,不带self和cls参数,并且被 @staticmethod 装饰的方法

class A:
	@staticmethod
	def f2():
		pass

属性

内置装饰器 @property 可以将方法变成实例变量的get 操作。但此时有可能会和真实的实例变量重名。

特殊成员

实例化

    def __new__(cls, *args, **kwargs):
        '''创建空实例,如果没有实现,则调用object 的此方法'''
        '''最先被调用的方法'''
        return object.__new__(cls)
    
    def __init__(self):
        '''初始化实例'''
        pass

实例对象化

    def __call__(self, *args, **kwargs):
        '''使类实例变成可调用对象'''
        pass

实例中数据字符串化

    def __str__(self):
        '''使类实例中的数据可变成字符串,可被str和print函数调用'''

实例中变量字典化

#直接调用即可将实例变量以字典的形式返回    
t=Test()
t.__dict__
class Test:
    def __getitem__(self, item):
        '''以字典访问的方式查找实例变量'''
        pass
    def __setitem__(self, key, value):
        '''以字典插入数据的方式对实例变量赋值'''
        print(key, value)
        pass
    def __delitem__(self, key):
        '''以del 的方式删除实例变量'''
        pass
    
t = Test()
t['k1'] = 1    #以字典方式赋值数据时,实际是调用了 __setitem__ 方法
print(t['k1']) #实际是调用了 __getitem__ 方法
del t['k1']    #实际是调用了 __delitem__ 方法

上下文管理

当使用with … as … 语法时,需要在对应的类里试下 __ enter __ 和 __ exit __ 两个方法,这两个方法分别对应创建和销毁上下文

class Test:
    def __enter__(self):
        print('__enter__')
    def __exit__(self, exc_type, exc_val, exc_tb):
        print('__exit__')


t = Test()
with t as f:   #此时调用 __enter__ 方法
    pass       #当执行完缩进代码块后调用 __exit__ 方法

数学运算符重载

class Test:
    def __add__(self, other):
        '''加,自加是 __iadd__ '''
        pass
    def __sub__(self, other):
        '''减,自减是 __isub__ '''
        pass
    def __mul__(self, other):
        '''乘,自乘是 __imul__ '''
        pass
    def __truediv__(self, other):
        '''除,结果带小数,自除是 __itruediv__ '''
        pass
    def __floordiv__(self, other):
        '''除,结果无小数,向下取整,自除是 __ifloordiv__ '''
        pass
    def __mod__(self, other):
        '''取模,自取模是 __imod__'''
        pass
    def __pow__(self, power, modulo=None):
        '''幂,自幂是 __ipow__ '''
        pass

逻辑运算符重载

class Test:
    def __lt__(self, other):
        '''小于'''
        pass
    def __gt__(self, other):
        '''大于'''
        pass
    def __eq__(self, other):
        '''等于'''
        pass
    def __le__(self, other):
        '''小于等于'''
        pass
    def __ge__(self, other):
        '''大于等于'''
        pass
    def __ne__(self, other):
        '''不等于'''
        pass

位运算符重载

class Test:
    def __and__(self, other):
        '''与'''
        pass
    def __or__(self, other):
        '''或'''
        pass
    def __xor__(self, other):
        '''异或'''
        pass
    def __lshift__(self, other):
        '''左移'''
        pass
    def __rshift__(self, other):
        '''右移'''
        pass

迭代器

如果实现迭代器(可迭代对象)

  1. 类中实现了 __ iter __ 和 __ next __ 两个方法;
  2. __ iter __ 方法需要返回一个可迭代对象,可以是其他可迭代对象实例或者当前实例自己,self;
  3. __ next __ 方法需要返回下一个数据,如果没有数据了,抛出StopIteration异常;

如果使用迭代器(可迭代对象)

  1. 使用next() 函数操作可迭代对象;
  2. 在for 循环中操作可迭代对象;
class Test:
    def __init__(self, num):
        self.num=num
    def __iter__(self):
        return self
    def __next__(self):
        self.num += 1
        if self.num >= 10:
            raise StopIteration
        else:
            return self.num

t=Test(4)
for tx in t:
    print(tx)  # 5, 6, 7, 8, 9

内置函数

# 检测对象是否实现了 __call__ 方法
callable(obj)

# 按照继承顺序去父类里找对应的方法和变量
# 如果是多继承,对父类的初始化需要使用未绑定方法
super()

# 返回对象的类名
type(obj)

# 检测对象是否为指定类的实例
isinstance(obj, Test)

# 检测两个类是否有继承关系
issubclass(cls1, cls2)

异常

使用异常

try:
    逻辑代码块
except Exception as e:try中的代码遇到异常时,此处代码块会被执行
finally:
    无论异常处理代码块是否执行,当try代码结束后都会执行此处代码,一般用于释放资源
    如果try里调用了return,则finally代码会在return 前被执行

自定义异常

class MyException(Exception):
    pass

# 必须要继承父类 Exception,在自定义类里可以用类变量或者实例变量记录此异常代表的错误信息

反射

反射是通过字符串在对象或模块中进行增删改查成员的操作。

反射要解决的问题:当要执行的方法或者变量名以字符串形式存储在其他变量里时,可以通过此变量操作相应对象或模块里的方法或变量。

python 支持反射的4个方法

  • hasattr 检测方法或变量在实例中是否存在
  • getattr 获取实例中的方法或变量
  • setattr 重置实例中的变量值,如果实例中无此变量,则新增此变量。不能操作方法
  • delattr 删除实例中的变量,如果变量不存在则会报错。不能操作方法
class Test:
    def __init__(self, name, age):
        self.name=name
        self.age=age
    def info(self):
        return "{}-{}".format(self.name, self.age)

op_name=input("请输入操作名称:")
t=Test("aizhaoyu", 18)
if hasattr(t, op_name):
    print("{} exists".format(op_name))
else:
    print("{} doesn't exist".format(op_name))
    exit(0)

op=getattr(t, op_name, None)
if callable(op):
    print("{} is a method".format(op_name))
else:
    print("{} is a variable".format(op_name))

    new_value=input("重置变量{}:".format(op_name))
    setattr(t, op_name, new_value)
    print(getattr(t, op_name, None))

    delattr(t, op_name)
    print(getattr(t, op_name, None))

网络编程

import socket
import select

# 和Linux C socket API基本一致
socket.socket()
setblocking()
bind()
listen()
connect()
close()
accept()  # 返回connection


# connection session
send/sendall()
recv()
close()

# IO 复用,和Linux C IO 复用API基本一致
select.select() #方法
select.poll()   #类
select.epool()  #类

你可能感兴趣的:(老亚瑟的技术备忘录,python,学习,开发语言)