初识面向对象
类:具有相同属性和技能的食物 语法:class 类名: 类名的首字母大写 例:class Person:
对象(实例):具体的某一事物;具体类的表现;具体的实实在在的一个实例
实例化:类---->对象的过程
例:
class Preson:
soup = "有灵魂"
language = "语言"
mind = "有思想"
def __init__(self, name, sex, age): #self:内存空间
self.name = name
self.sex = sex
self.age = age
def eat(self):
print("%s在吃饭" % self.name)
def sleep(self):
print("%s在睡觉" % self.name)
def work(self):
print("%s在工作" % self.name)
调用:
类名角度
1.调用类中的静态变量
方法一: 函数__dict__ 只能进行查找 不能进行增删改
例:
print(Preson.__dict__)
结果:{'__module__': '__main__', 'soup': '有灵魂', 'language': '语言', 'mind': '有思想', '__init__': <function Preson.__init__ at 0x000001E43FCD1A60>, 'eat': <function Preson.eat at 0x000001E43FCD1AE8>, 'sleep': <function Preson.sleep at 0x000001E43FCD1B70>, 'work': <function Preson.work at 0x000001E43FCD1BF8>, '__dict__': <attribute '__dict__' of 'Preson' objects>, '__weakref__': <attribute '__weakref__' of 'Preson' objects>, '__doc__': None}
例:
print(Preson.__dict__["soup"]) ==>有灵魂
方法二: " . " 进行增删改查
例:
print(Preson.soup)
Preson.money = "运用货币"
Preson.language = "使用语言"
del Preson.soup
print(Preson.__dict__)
结果:有灵魂
{'__module__': '__main__', 'language': '使用语言', 'mind': '有思想', '__init__': <function Preson.__init__ at 0x000002194CF21A60>, 'eat': <function Preson.eat at 0x000002194CF21AE8>, 'sleep': <function Preson.sleep at 0x000002194CF21B70>, 'work': <function Preson.work at 0x000002194CF21BF8>, '__dict__': <attribute '__dict__' of 'Preson' objects>, '__weakref__': <attribute '__weakref__' of 'Preson' objects>, '__doc__': None, 'money': '运用货币'}
2.用类名调用类中的方法 基本不用
对象角度
1.对象操作类中的静态变量只能查
例:
print(p.soup) ==>有灵魂
2.对象操作类中的方法 第一个参数self不用传
例:
p.work() ==>小白在工作
实例化对象/实例/对象:
类名+()的过程叫实例化过程(创建一个对象的过程)
例:
p = Preson("小白", "男", 24)
print(p.__dict__)
结果:{'name': '小白', 'sex': '男', 'age': 24}
(1).类名+()产生一个实例(对象.对象空间)
(2).自动执行类中的__init__方法,将对象空间传给__init__的self参数
(3).给对象封装属性
__init__函数参数(属性)的增删改查
例:
p.height = 185 #增
del p.age #删
p.name = "小黑" #改
print(p.sex) #查
print(p.__dict__)
==>男
{'name': '小黑', 'sex': '男', 'height': 185}
查询顺序:
在执行类名()时产生一个含有类对象指针的空间
(1).对象>属性:先从对象空间找,如果找不到再从类空间找,再找不到再从父类找.
(2).类名>属性:先从本类空间找,如果找不到再从父类空间找
对象和对象之间是互相独立的
例:计算实例化的次数
class Preson:
count = 0
def __init__(self):
Preson.count = Preson.count + 1
obj1 = Preson()
obj2 = Preson()
obj3 = Preson()
print(Preson.count) ==>3
通过类名可以更改类中的静态变量值,但是通过对象不能改变,只能引用类中的静态变量
组合:给一个类的对象封装一个属性,这个属性是另一个类的对象
例:
class GameRole:
def __init__(self,name,ad,hp):
self.name = name
self.ad = ad
self.hp = hp
def attack(self,p):
p.hp = p.hp - self.ad
print("%s攻击了%s,%s掉了%s血,还剩%s血" % (self.name,p.name,p.name,self.ad,p.hp))
def armament_weapon(self,wea):
self.wea = wea
class Weapon:
def __init__(self,name,ad):
self.name = name
self.ad = ad
def fight(self,p1,p2):
p2.hp = p2.hp - self.ad - p1.ad
print("%s用来%s打了%s,%s掉了%s血,还剩%s血" % (p1.name,self.name,p2.name,p2.name,self.ad,p2.hp))
p1 = GameRole("灰太狼",20,500)
p2 = GameRole("红太狼",50,300)
w1 = Weapon("平底锅",70)
p2.armament_weapon(w1)
p2.wea.fight(p2,p1)
结果:红太狼用来平底锅打了灰太狼,灰太狼掉了70血,还剩380血
面向对象的三大特点:继承.多肽.封装
继承好处:
b:提高了代码的维护性
c:让类与类之间产生了关系,是多态的前提
例:子类既要执行子类的方法,又要执行父类的方法
class Animal:
def __init__(self,name,sex,age):
self.name = name
self.sex = sex
self.age = age
def eat(self):
print("%s吃东西" % self.name)
def drink(self):
print("喝水")
class Dog(Animal):
def action1(self):
print("会看门")
class Cat(Animal):
def action2(self):
print("会抓老鼠")
class Chicken(Animal):
pass
class Bird(Animal):
def __init__(self,name,sex,age,wing):
# Animal.__init__(self,name,sex,age)
super().__init__(name,sex,age) #super只能在子类中使用
# super(Bird,self).__init__(name,sex,age)
self.wing = wing
def eat(self):
super().eat()
print("%s吃虫子" % self.name)
d1 = Dog("小黑","女",5)
c1 = Cat("白白","女",2)
m1 = Chicken("小花","女",2)
c1.eat()
c1.action2()
b1 = Bird("鹦鹉","公",20,"花翅膀")
b1.eat()
结果:
白白吃东西
会抓老鼠
鹦鹉吃东西
鹦鹉吃虫子
多继承
类:经典类和新式类
经典类:不继承object函数的都是经典类 在python2所有的类都不继承object所有的类默认是经典类,可以添加object变成新式类 查询遵循:深度优先
新式类:凡是继承object函数的都是新式类 在python3中所有的类都默认继承object.所有的类都是新式类 查询遵循:广度优先
例:
class A:
def fn(self):
print("in A")
class B(A):
def fn(self):
print("in B")
class C(A):
def fn(self):
print("in C")
class D(B):
def fn(self):
print("in D")
class E(C):
def fn(self):
print("in A")
class F(D,E):
def fn(self):
print("in A")
f1 = F()
f1.fn()
print(F.mro()) #查询类的继承顺序只适用于新式类
广度优先: 每个节点有且只走一次
一路走到倒数第二级,判断 如果其它路能走到终点,则走另一条路, 如果走不到则接着走
深度优先: 一条路走到底
多继承(C3)算法原理:
例:
class H:
def fn(self):
print("H fn")
class G(H):
def fn(self):
print("G fn")
class F(H):
def fn(self):
print("F fn")
class E(G):
def fn(self):
print("E fn")
class D(F):
def fn(self):
print("D fn")
class C(E):
def fn(self):
print("C fn")
class B(D):
def fn(self):
print("D fn")
class A(B,C,D):
def fn(self):
print("A fn")
a = A()
print(A.mro())
结果:[<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class '__main__.F'>, <class '__main__.E'>, <class '__main__.G'>, <class '__main__.H'>, <class 'object'>]
接口类:
接口类和抽象类的定义:制定一个规范 思想:归一化接口设计
例:
class Alipay:
def __init__(self,money):
self.money = money
def pay(self):
print("使用支付宝支付%s" % self.money)
class Jdongpay:
def __init__(self,money):
self.money = money
def pay(self):
print("使用京东支付%s" % self.money)
def pay(obj):
obj.pay()
a1 = Alipay(200)
j1 = Jdongpay(100)
pay(a1)
pay(j1)
结果:
使用支付宝支付200
使用京东支付100
强制制定一个规范:凡是继承基类的子类中必须有...方法,如果没有实例化对象会报错
例:
from abc import ABCMeta,abstractmethod
class Payment(metaclass=ABCMeta):
@abstractmethod
def pay(self):pass #每一个继承Payment类的子类必须含有pay方法
class Alipay(Payment):
def __init__(self,money):
self.money = money
def pay(self):
print("使用支付宝支付%s" % self.money)
def pay(a):
a.pay()
p1 = Alipay(200)
pay(p1) ==>使用支付宝支付200
多态 :
python没有多态概念,处处都是多态
python没有多态,它有鸭子类型
鸭子类型:看着像鸭子,他就是鸭子 ------几个类中都含有相同的方法,互成为鸭子
例:
class Str:
def index(self):
pass
class List:
def index(self):
pass
class Tuple:
def index(self):
pass
封装:
广义的封装:实例化一个对象,给对象空间封装一些属性
狭义的封装:私有制
私有成员:私有静态属性,私有方法,私有对象属性,私有类方法,私有静态方法
例:
class Person:
mind = "有思想"
__soul = "灵魂" #私有静态变量
def __eat(self): #私有方法
print("吃饭")
def __init__(self,money): #私有属性
self.__money = money
类的外部(类名.实例化对象.子类)不能访问私有静态变量
类的内部可以访问
例:
class Person:
mind = "有思想"
__soul = "灵魂" #私有静态变量
def __eat(self): #私有方法
print(self.__soul)
print("吃饭")
def drink(self):
print("喝水")
def __init__(self,money): #私有属性
self.__money = money
p1 = Person(100)
p1.drink() ==>喝水
#类外部也可以访问
#print(Person._Person__soul) ==>灵魂
私有方法和私有属性的内部调用
例:
class Person:
mind = "有思想"
__soul = "灵魂" #私有静态变量
def __eat(self): #私有方法
print("吃饭")
def __init__(self,money): #私有属性
self.__money = money
def drink(self):
print("喝水")
self.__eat() #内部调用私有eat方法
def money(self):
print("花了%s块钱" % self.__money) #内部调用私有money属性
p1 = Person(100)
p1.drink() ==>喝水 吃饭
p1.money() ==>花了100块钱
print(Person._Person__soul) #在类外面也可以调用私有方法但一般不用 ==>灵魂
例:
class Parent:
def __func(self):
print("in Parent func")
def __init__(self):
self.__func() <==> self._Parent__func()
class Son(Parent):
def __func(self):
print("in Son func")
son1 = Son() ==>in Parent func
伪装属性:
将一个方法伪装成一个属性,在代码的级别没有本质的提升,但是让其看起来更合理
用在类似名词却需要计算的地方例如:BMI,面积,周长等
例:
class Heather:
def __init__(self,name,weight,height):
self.name = name
self.__weight = weight
self.__height = height
@property
def bmi(self):
BMI = round(self.__weight/self.__height**2,2)
print("%s的体脂数是%s" % (self.name,BMI))
p1 = Heather("小白",55,1.75)
p1.bmi ==>小白的体脂数是17.96
属性的改值:
例:
class Person:
def __init__(self,name,age):
self.name = name
self.__age = age
@property
def age(self): 方法名字要相同
return self.__age
@age.setter
def age(self,a1): 把要修改的值传给a1
print(a1)
p1 = Person("小白",24)
p1.age = 26
p1.age ==>26
例:判断年龄是不是整数 和 删除属性
class Person:
def __init__(self,name,age):
self.name = name
self.__age = age if type(age) is int else print("您输入的格式不正确")
@property
def age(self):
return self.__age
@age.setter
def age(self,a1):
self.__age = a1 if type(a1) is int else print("您输入的格式不正确!")
@age.deleter
def age(self):
del self.__age
p1 = Person("小白",19)
p1.age = 20
print(p1.age) ==>20
del p1.age
print(p1.__dict__) ==>{'name': '小白'}
三级运算:True:part if 条件判断 else False:part
类方法:
通过类名调用的方法,类方法中第一个参数约定俗称cls,python自动将类名(类空间)传给cls.
例:
class A:
def func(self):
print(self)
@classmethod
def func1(cls):
print(cls)
a1 = A()
print(a1.func)
print(A.func1)
a1 = A()
a1.func1() 对象调用类方法,传给cls参数也是该对象的所属类,cls得到的是类本身
结果:
<bound method A.func of <__main__.A object at 0x000001D7362BFF28>>
<bound method A.func1 of <class '__main__.A'>>
<class '__main__.A'>
类方法的应用:
(1).类中有些方法是不需要传入对象,不要对象的一切东西(不需要对象的参与)
例:
class Person:
name = "小白"
count = 1
@classmethod
def func(cls):
return cls.name+str(cls.count+1)
print(Person.func()) ==>小白2
(2).对类中的静态变量进行改变要用类方法
(3).在继承中父类得到子类的类空间
例:
class A:
age = 19
@classmethod #类方法---对子(B)类中的所有内容都可以进行访问和修改
def func(cls):
print(cls)
def func1(self): #方法--只能访问子(B)类中的所有内容
print(self)
class B(A):
age = 22
B.func() ==><class '__main__.B'>
静态方法:
例:
class A:
@staticmethod
def func():
print("123")
A.func() ==>123
静态方法的优点:
(1).代码块清晰
(2)复用性,减少代码量