内置方法:
当对对象按照字典方式操作时,会自动触发相关方法
示例:
class Person: # 当对对象按照字典设置键值对时,会自动触发该方法 def __setitem__(self, key, value): # print(key, value) self.__dict__[key] = value # 当对对象按照字典操作根据键获取值时,会自动触发该方法 def __getitem__(self, item): # print(item) return self.__dict__[item] # 当做字典操作,删除键值对时,自动触发该方法 def __delitem__(self, key): # print(key) del self.__dict__[key] p = Person() p['name'] = 'xiaoming' print(p['name']) # 通过字典方式添加的键值对,可以通过属性的方式获取 print(p.name) print(p.dict) del p['name']
类的继承
相关概念:
继承:父类的属性和方法子类可以直接拥有称为继承
派生:子类在父类的基础上衍生出来的新的特征(属性和方法)
总结:其实他们是一回事,只是描述问题的角度侧重点不同(继承侧重相同点,派生侧重不同点)
相关语法:
# class Animal(object): # 当没有指定父类时,相当默认父类为object class Animal: def __init__(self, name): self.name = name def eat(self): print('小动物喜欢一天到晚吃个不停') # 继承自Animal class Dog(Animal): pass d = Dog('旺财') # 直接拥有父类的方法 d.eat() # 直接拥有父类的属性 print(d.name)
派生:子类可以扩充属性和方法
class Animal: def run(self): print('小动物喜欢到处乱跑') class Rabbit(Animal): # 添加方法 def eat(self): print('爱吃萝卜和青菜') xiaobai = Rabbit() xiaobai.run() xiaobai.eat() # 添加属性 xiaobai.color = 'white' print(xiaobai.color)
重写:
父类的方法完全不合适,子类需要全部的覆盖
父类的方法合适,但是需要完善
示例:
class Animal: def run(self): print('小动物喜欢到处乱跑') def eat(self): print('小动物也是一天三顿') class Cat(Animal): # 当父类的方法完全不合适时,可以覆盖重写 def run(self): print('俺走的是猫步') # 父类的方法合适,但是子类需要添加内容完善功能 def eat(self): # 调用父类方法,不建议使用 # Animal.eat(self) # super(Cat, self).eat() # 类名及self可以不传 super().eat() print('不过俺喜欢吃鱼') jiafei = Cat() jiafei.run() jiafei.eat()
多继承
概念:一个类可以有多个父类
示例:
class A: def eat(self): print('eat func of A') class B: def eat(self): print('eat func of B') # 多继承,多个父类使用逗号隔开 class C(B, A): def eat(self): # 当多个父类拥有相同的方法时,会按照继承时的先后顺序进行选择 # super().eat() # 如果非要使用后面的类的方法时,可以明确指定进行调用 A.eat(self) c = C() c.eat()
访问权限
权限:
公有的:类中的普通属性和方法,默认都是公有的,可以在类的内部、外部、子类中使用
私有的:定义是在前面加两个'_',只能在本类的内部使用,不能再外部及子类中使用
示例:
class Person: def __init__(self, name, age): self.name = name # 在属性的前面添加两个'_',外部访问,系统内部的除外 # 默认的属性名:__age => _Person__age self.__age = age def eat(self): print('民以食为天') # 在方法的前面添加两个'_' def __inner(self): print('私有方法,不想让外部调用') def test(self): # 在类的内部可以访问私有的属性和方法 print(self.__age) self.__inner() p = Person('老王', 50) # 默认所有的属性和方法都是公有的,就是在类的外面可以直接使用 p.eat() print(p.name) # 一下两句会报错,提示没有相关的属性或方法 # p.__inner() # print(p.__age) # print(p.__dict__) # 可以通过系统修改的名称找到,但是强烈建议不要这样使用 print(p._Person__age) p._Person__inner() p.test() class Man(Person): def test(self): # print(self.__age) # self.__inner() print('子类无法使用父类私有的属性和方法') m = Man('木盖', 24) m.test()
类属性
说明:定义类时,写在类中,但是方法外的属性,通过放在类的开头位置
示例:
class Person: # 定义类属性 nation = '中国' def __init__(self, name): self.name = name self.nation = 'china' # 通过类名访问类属性 print(Person.nation) p = Person('xiaoming') # 通过对象也可访问类属性,但是不建议 # 当对象有同名的成员属性时,使用的就是成员属性 print(p.nation) # 也可以动态添加 Person.hello = 'hello' print(Person.hello) # 特殊的类属性 # 表示的类名字符串 print(Person.__name__) # 表示父类构成的元组 print(Person.__bases__) # 存储类相关的信息 print(Person.__dict__)
类方法
说明:
定义时使用装饰器:classmethod
通过类名进行调用
作用:
可以创建对象或者简洁的创建对象
对外提供简单易用的接口
示例1:语法:
class Person: def eat(self): print('麻辣是我的最爱') # 使用装饰器 classmethod 修饰的方法 就是类方法 def test(cls): print('类方法 test') # cls 表示当前类 print(cls) def create(cls): p = cls() # 进行特定的初始化设置 p.age = 1 return p Person.test() # print(Person) # 可以创建或者简洁的创建对象 p = Person.create() print(p)
示例2:设计一个数字类,用于两个属性,能够进行加减乘除运算,要求:计算两个数的平方和
class Number: def __init__(self, num1, num2): self.num1 = num1 self.num2 = num2 def add(self): return self.num1 + self.num2 def sub(self): return self.num1 - self.num2 def mul(self): return self.num1 * self.num2 def div(self): if self.num2 == 0: return None return self.num1 / self.num2 def pingfanghe(cls, num1, num2): # 第一个数 n1 = Number(num1, num1) # 求平方 n12 = n1.mul() # 第二个数 n2 = Number(num2, num2) # 求平方 n22 = n2.mul() # 第三个数 n3 = Number(n12, n22) return n3.add() he = Number.pingfanghe(3, 4) print(he)
静态方法
说明:
使用装饰器:staticmethod进行修饰
定义的方法没有第一个表示当前类参数
示例:
class Person: def test(): print('static method test') def create(): # 也可以创建对象 p = Person() return p Person.test() p = Person.create()
与类方法对比:
除了装饰器不同,其他基本一样,做与对象创建无关的任务时可以使用静态方法
所有静态方法能够完成的功能都是使用类方法完成
多态特性
定义:不同的对象,调用相同的方法有不同的响应称为多态
体现:多态性,不同对象接收相同的消息会有不同的响应。
示例:
class Animal: def run(self): pass class Dog(Animal): def run(self): print('狗奔跑的时候一般是s型') class Cat(Animal): def run(self): print('猫平时走猫步,偶尔会突然加速') # 参数必须有run方法 def func(obj): obj.run() func(Dog()) func(Cat())
属性函数
说明:就是将方法当做属性一样
作用:保护特定属性,处理特定属性
示例:
class User: def __init__(self, username, password): self.username = username self.__password = password # 使用property修饰的方法,可以当做属性访问 # 可以保护特定的属性 def password(self): print('有人想直接获取密码') # return self.__password return '哈哈,想偷看,没门' # 当设置password属性时,会自动调用该方法 .setter def password(self, password): print('注意了,有人想修改密码', password) # 可以对密码进行特定处理,然后保存 self.__password = 'xxx'+ password+'yyy'
u = User('xiaoming', '123456') print(u.username) # 很多时候直接访问密码是不需要的,也是不安全的 # 直接访问password属性,自动回调用使用property修饰后的password方法 print(u.password) u.password = '654321'
### 内置方法 - 说明: - 当将对象当做函数一样调用时,系统会自动触发 __ call __ 方法 - 若想支持这样的操作,系统在类中提供 __ call __ 方法 - 示例: ```python class Person: # 当对象当做函数一样调用时,系统会自动触发该方法 def __call__(self, *args, **kwargs): # 如:计算和 return sum(args) p = Person() # 将对象当做函数使用,需要提供 __call__ 方法 ret = p(1,2,3, name='xiaoming') print(ret)
函数判断
问题:如何判断一个对象是否可以像函数一样调用
示例:
class A: def __call__(self, *args, **kwargs): print('xx') def test(): pass # 不能使用isinstance方法判断一个对象是否是函数 # isinstance(test, function) # 打印时仍然是function类型 # print(type(test)) # 判断一个对象是否可以像函数一样调用 print(callable(test)) a = A() print(callable(a)) # 判断对象是否拥有 call属性 print(hasattr(test, 'call')) print(hasattr(a, 'call')) # 判断是否是函数 from inspect import isfunction print(isfunction(test)) print(isfunction(a))
数据持久化存储
方式:普通文件、数据库、序列化
示例: