类与对象
类
class Person:
def __init__(self):
self.name = "Luo"
self.mystr = "任你千般芳华万般妖娆,我只问一句,可解Bug否?"
def work(self):
print("生命不息,奋斗不止!")
p1 = Person()
print(p1.name)
print(p1.mystr)
p1.work()
类的定义与结构
class 类名:
def __init__(self, 形参1, 形参2):
self.属性1 = 形参1
self.属性2 = 形参2
def __del__(self):
pass
类的介绍
- class关键字修饰类
- init方法用于类的初始化自动调用
- del方法(析构函数)用于类被销毁时自动调用
类的权限设计
class Bank:
def __init__(self, money, yearRate, year):
self.__money = money
self.__yearRate = yearRate
def __getRateMoney(self):
return self.money * (1 + self.yearRate)**year
def getMoney(self):
self.__getRateMoney()
bank = Bank(10000, 0.04, 10)
bank.getmoney()
类的权限设计注意点
- 加上双下划线,变量和方法就变成私有的了,外部不能直接访问
- 私有变量和方法可通过 对象._类名__变量名访问
类内部访问私有变量的方式
class Circle:
def __init__(self, radius):
self.__radius = radius
def getRadius(self):
return self.__radius
这里外部不能访问 __radius 属性
c1 = Circle(5)
c1.__radius 和 c1.radius 都不能访问到 radius 这个私有变量
-----------------------
下面这种方式才能访问私有变量
c1.getRadius()这个能访问到 self.__radius 这个私有变量的值
类外部访问私有变量的方式
1. Python私有变量在类内部的命名特性,根据 name mangling 技术,
2. 私有变量的名字都会变成(_类名__变量名)的形式
class Circle:
def __init__(self, radius):
self.__radius = radius
def getRadius(self):
return self.__radius
c1 = Circle(5)
c1._Circle__radius 这个能访问到 self.__radius
实例变量(类修改变量值不会对实例变量产生影响)
- 一个类修改实例变量不会影响该类创建时候该类实例变量的值
类变量(类修改变量的值会影响类实例调用该变量的值)
- 类也会创建一个实例,每次创建一个对象时都会从类中拷贝类的所有状态
- 如果在创建一个类之前通过类名修改了类的不可变变量的值,创建的实例中的值也会相应的改变,但是实例变量修改不会影响类变量
- 如果在创建一个类之前通过类名修改了类的可变变量的值,创建的实例中的值也会相应的改变,但是实例变量修改会影响类变量
继承
- 儿子的属性和方法会覆盖父亲类
- 儿子类继承所有父类非私有方法和属性
- 儿子想自己也拥有自己的属性需要调用父类的init方法
继承的格式
class 类1(类2):
pass
继承的用法
class Person:
def __init__(self):
self.name = "Luo"
self.mystr = "任你千般芳华万般妖娆,我只问一句,可解Bug否?"
def work(self):
print("生命不息,奋斗不止!")
class Luo(Person):
pass
luo1 = Luo()
print(luo1.name)
print(luo1.mystr)
luo1.work()
经典类与新式类
class People: 经典类写法
pass
class Man:
def __init__(self,name,age):
People.__init__(self,name,age) 经典类写法
class People(object): 新式类的写法
def __init__(self,name,age):
super(Man,self).__init__(name,age) 新式类的写法
Python2/3中经典类与新式类继承方式
- py2中经典类时按照深度优先来继承的,新式类时按照广度优先来继承的
- py3中经典类与新式类都是统一按照广度优先来继承的
多继承
- 多继承情况下,如果该类想拥有自己的属性,那么必须用类名去分别调用init方法
- 属性后面调用的init覆盖前面调用的(后覆盖前)
- 方法会前者覆盖后者
多继承用的场合
- 同时要用到多个类的功能就需要多继承
继承的局限性
- 无法拿到父类的私有方法与属性(通过父类名还是能拿到)
类的一般属性
- doc:类的说明(类似文档注释)
- name:类的名字
- module:从哪开始执行的
- bases:类的多个父类
- base:类的单个父类
- dict:类全部信息,以字典的形式
- class:当前类的类型
super关键字
- 父类少初始化,节省内存
多态接口
class F:
def show(self):
print("F Show")
class A(F):
def show(self):
print("A Show")
class B(F):
def show(self):
print("B Show")
def Fun(C):
C.show()
a = A()
b = B()
Fun(a)
Fun(b)
--------------------------------
class Animal:
def __init__(self, name):
self.name = name
def talk(self):
pass
@staticmethod
def animal_talk(obj):
'''接口'''
obj.talk()
class Cat(Animal):
def talk(self):
print('Meow!')
class Dog(Animal):
def talk(self):
print('Woof! Woof!')
d = Dog("D1")
c = Cat("C1")
Animal.animal_talk(c)
Animal.animal_talk(d)
多态介绍
- 因为Python定义参数不需要数据类型,所以在Python中用方法当做接口去实现多态
- 为了解决不同对象的各种需求,接口就应运而生了
类的动态绑定属性和方法
- 类可以在对象创建时动态添加属性和方法
- 动态添加的属性和方法只在当前对象有用,对其他对象无影响
动态添加属性
class XiaoA:
pass
xiaoA = XiaoA()
xiaoA.女神的备胎数量 = 99 # 动态添加的
动态添加方法
class XiaoA:
def __init__(self):
self.女神的备胎数量 = 99
def 中奖(self):
self.女神的备胎数量 = 0
xiaoA = XiaoA()
xiaoA.中奖 = types.MethodType(中奖, xiaoA)
xiaoA.中奖()
print(xiaoA.女神的备胎数量) --> 0
类的属性动态操作
判断当前对象是否有某属性
hasattr(对象,"属性名")
设置当前对象的属性(有该属性就覆盖值)
setattr(对象, "属性名", 设置值)
读取属性的细节
- 如果有该属性就返回该属性值,没有就返回默认值
读取这个对象的属性
getattr(对象, "属性名", 默认值)
读取属性的细节
- 如果有该属性就返回该属性值,没有就返回默认值
类的方法动态操作
判断当前对象是否有某方法
hasattr(对象,"方法名")
设置当前对象的方法(有该属性就覆盖值)
class XiaoA:
def __init__(self):
self.女神的备胎数量 = 99
def 中奖(self):
self.女神的备胎数量 = 0
xiaoA = XiaoA()
xiaoA.中奖 = types.MethodType(中奖, xiaoA)
xiaoA.中奖()
print(xiaoA.女神的备胎数量) --> 0
读取方法的细节
- 如果有该方法就返回该方法
读取这个对象的属性
getattr(对象, "属性名", 默认值)
对象属性方法与类属性方法
class XiaoA:
def __init__(self):
self.女神的备胎数量 = 99 # 类属性
xiaoA.name = "xiaoB" # 对象属性
限制属性(只能操作和使用限制的属性)
class XiaoA:
__slots__ = ("name", "love")
xiaoA = XiaoA()
xiaoA.name="xiaoA"
xiaoA.love = "xiaoB"
xiaoA.loveother = "aaa" # 会报错
类方法与静态方法和属性方法
class XiaoA:
@classmethod
def love(self):
self.name=
类方法介绍
- @classmethod修饰的方法是类方法
- 类方法可以用类名调用,也可以用对象调用
- 类方法无法覆盖类属性,可以在这里初始化
- 必须加上self
- 只能访问类变量,不能访问实例变量
静态方法
- 静态方法实际上和类没有关系了,仅仅只要类名调用
- @staticmethod修饰的方法是静态方法
- 静态方法可以用类名调用,也可以用对象调用
- 参数可以不带self
- 作用一般多态会用到,或者一个工具类集合
静态方法与类方法的对比
- 不用加self,其他差不多
属性方法property(类似Java中get/set方法)
- 把一个方法变成一个属性,然后像属性一样用,不用加括号调用
- 屏蔽信息获取解析过程,只暴露结果
静态方法
class Dog(object):
def __init__(self,name):
self.name = name
@staticmethod #实际上跟类没什么关系了
def eat(self):
print("%s is eating %s" %(self.name,'dd'))
def talk(self):
print("%s is talking"% self.name)
d = Dog("ChenRonghua")
d.eat(d)
d.talk()
类方法
class Dog(object):
#n = 333
#name = "huazai"
def __init__(self,name):
self.name = name
#self.n = 333
#@staticmethod #实际上跟类没什么关系了
@classmethod
def eat(self):
print("%s is eating %s" %(self.name,'dd'))
def talk(self):
print("%s is talking"% self.name)
d = Dog("ChenRonghua")
d.eat()
属性方法
class Flight(object):
def __init__(self,name):
self.flight_name = name
def checking_status(self):
print("checking flight %s status " % self.flight_name)
return 0
@property
def flight_status(self):
status = self.checking_status()
if status == 0 :
print("flight got canceled...")
elif status == 1 :
print("flight is arrived...")
elif status == 2:
print("flight has departured already...")
else:
print("cannot confirm the flight status...,please check later")
@flight_status.setter
def flight_status(self,status):
print("flight %s has changed status to %s" %(self.flight_name,status))
@flight_status.deleter
def flight_status(self):
del self.flight_name
f = Flight("CA980")
f.flight_status
f.flight_status = 2
枚举类
import enum # 枚举
@enum.unique
class 象棋(enum.Enum):
帅=1000 # 无需排序
车=10
马=5
炮=5
枚举类的介绍
- 象棋.帅.value # 象棋.帅的值
- 象棋.帅.name # 象棋.帅的名字
动态创建类
def show(self,name):
print("我是", name)
# A是类的名字,(object父类) dict字典
A = type("A", (object,), dict(showname = show))
a = A() # 初始化
a.showname("Luo") # 调用了show方法
print(type(A)) # type类型:动态类型
print(type(a)) # A类型,两个A可以不一样
动态创建类第二版
def func(self):
print("hello %s"%self.name)
def __init__(self,name,age):
self.name = name
self.age = age
Foo = type("Foo",(object,), {"talk":func,"__init__":__init__})
f = Foo("Luo",22)
f.talk()