一、OO = Object Oriented 面向对象
OOP面向对象编程、OOA面向对象分析、OOD面向对象设计
二、属性+方法——>类(数据和函数)
class Turtle(): #类名约定用大写 #属性 color = #方法 def climb(self): pass def run(self): pass tt = Turtle() #创建对象 tt.run() #调用 class Myclass(list):继承list pass list2 = Myclass() list2.append(4) list2.append(3) list2.sort()
class A:
def fun(self):
print('I am A')
class B:
def fun(self):
print('I am B')
a = A()
b = B()
a.fun()
b.fun()#名字一样,打印不一样,就是多态
OOP三大特征:
封装:信息隐蔽技术
继承:子类自动共享父类之间数 据和方法的机制
多态:不同对象对同一方法响应不同的行动
三、self是什么?相当于c++的this指针!
由一个类可以生成无数个对象,当一个对象的方法被调用的时候,对象会把自身作为第一个参数传给self参数,Python就知道是哪个对象在调用方法了。例如:
class Ball(): def setName(self, name): self.name = name def kick(self): print("我叫%s,谁踢我。。。" % self.name) a = Ball() a.setName('qiu A') b = Ball() b.setName('qiu B') a.kick() b.kick() #a对象和b对象个返回个的,正是因为self的帮助
四、Python的魔法方法(被双下滑线包围)
__init__(self)构造方法,用于实例化对象传入参数
上边两个例子没有显性声明构造方法,试用默认的无惨__init__()
#coding:utf8 class Ball: def __init__(self, name): self.name = name def kick(self): print("I am %s, 该死的,谁踢我" % self.name) a = Ball('土豆') a.kick()
c = Ball() #报错
五、公有和私有
公有变量可以通过点操作符访问
私有变量(名字改编"_类名__变量名"name mangling技术)只需在变量名或函数名前加上“__”两个下划线!此时点name或者点__name都不能访问到(报错),试用getName()
#coding:utf8 class Person: __name = "liyi" def getName(self): #通过方法访问 return self.__name p = Person() #p.name 报错 #p.__name 报错 p.getName() p._Person__name #会访问到liyi
私有方法也是加两个下划线
python:类5——Python 的类的下划线命名有什么不同?
六、继承
1、如果子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法或属性
#coding:utf8 class Parent: def hello(self): print('父类方法hello') def func(self): print('父类方法func') class Child(Parent): def func(self): print('子类方法func,覆盖了父类方法') p = Child() p.hello() p.func() [root@CentOS6 ~]# python test.py 父类方法hello 子类方法func,覆盖了父类方法
2、supper()方法
(技术一:调用未绑定的父类方法)调用父类的构造方法(父类点init方法,注意self参数),
此处的self不是分类的实例对象,而是子类Shark的实例对象,相当于Fish.__init__(Shark),因为被重写了。
(技术二:使用supper函数<更好>):supper函数能自动找到需要的基类的方法,而且还会为我们自动传入self参数
supper().__init__(),不用给出基类的名字,会自动把所有父类、父父类的方法;所以修改基类名字时,不用一一修改
#coding:utf8
import random as r
class Fish:
def __init__(self):
self.x = r.randint(0, 10) self.y = r.randint(0, 10) def move(self): self.x -= 1 print("我的位置是:", self.x, self.y) class Goldfish(Fish): pass class Carp(Fish): pass class Salmon(Fish): pass class Shark(Fish): #定义鲨鱼,除了位置属性还要有个是否饥饿的属性 def __init__(self): #重写就会覆盖
Fish.__init__(self) #(技术一:调用未绑定的父类方法)
(技术二:使用supper函数<更好>)
self.hungry = True def eat(self): if self.hungry: print("吃货的梦想就是天天有的吃") self.hungry = False else: print("太撑了,吃不下了") g = Goldfish() s = Shark() s.eat() g.move()
3、多重继承:会使语法混乱,尽量不用
class Base1: pass class Base2: pass class C(Base1, Base2): pass
七、组合类:把类的实例化放到新类里边(横向关系,继承是纵向关系)
#coding:utf8
把鱼类对象和乌龟类对象放到水池类中 class Turtle: def __init__(self, x): self.num = x class Fish: def __init__(self, x): self.num = x class Pool: def __init__(delf, x, y): #传入x个乌龟y个鱼 self.turtle = Turtle(x) self.fish = Fish(y) def print_num(self): print("水池总共有乌龟%d只,小鱼%d条" % (self.turtle.num, self.fish.num) #这里self.turtle是不对的,必须是self.turtle.num
八、Mix-in机制(鱼c扩展)
pass
九、类、类对象、实例对象:是三个不同的东西!
#coding:utf8 class C: #类 count = 0 a = C() b = C() a.count #实例对象的count C.count #类对象的count
a.count = 10 #a.count返回10 b.count返回0 C.count返回0
C.count = 100 #a.count返回10(因为上一步已经覆盖,看不到上一层) b.count返回100(未覆盖,看到上一层) C.count返回100
对实例对象赋值后,会覆盖掉类对象,而看不到类对象
下边的会覆盖上边的!
十、属性和方法相同,属性会把方法覆盖掉!
属性名用名词,方法名用动词
扩展:Python绑定概念
Python严格要求方法需要有实例才能被调用,这种限制其实就是Python所谓的绑定概念。所以需要在方法定义时加上self
bb.__dict__查看实例所拥有的属性
BB.__dict__查看类所拥有的的属性,可以看到方法,会有好多东西,用来跟踪与类相关的值。实例对象会共用,但会被实例属性覆盖;以dict键值对返回
删除类对象后,实例对象(static静态的)依然存在在内存中,只有当程序退出时才会释放。