类与对象
1. 对象 = 属性 + 方法
1. 封装:信息隐蔽技术
我们可以使用关键字 class 定义 Python 类,关键字后面紧跟类的名称、分号和类的实现。
class Turtle: # Python中的类名约定以大写字母开头
"""关于类的一个简单例子"""
# 属性
color = 'green'
weight = 10
legs = 4
shell = True
mouth = '大嘴'
# 方法
def climb(self):
print('我正在很努力的向前爬...')
def run(self):
print('我正在飞快的向前跑...')
def bite(self):
print('咬死你咬死你!!')
def eat(self):
print('有得吃,真满足...')
def sleep(self):
print('困了,睡了,晚安,zzz')
tt = Turtle()
print(tt)
# <__main__.Turtle object at 0x0000007C32D67F98>
print(type(tt))
# <class '__main__.Turtle'>
print(tt.__class__)
# <class '__main__.Turtle'>
print(tt.__class__.__name__)
# Turtle
tt.climb()
# 我正在很努力的向前爬...
tt.run()
# 我正在飞快的向前跑...
tt.bite()
# 咬死你咬死你!!
# Python类也是对象。它们是type的实例
print(type(Turtle))
# <class 'type'>
**.继承:**子类自动共享父类之间数据和方法的机
class MyList(list):
pass
lst = MyList([1, 5, 2, 7, 8])
lst.append(9)
lst.sort()
print(lst)
# [1, 2, 5, 7, 8, 9]
多态:不同对象对同一方法响应不同的行动
def run(self):
raise AttributeError('子类必须实现这个方法')
class People(Animal):
def run(self):
print('人正在走')
class Pig(Animal):
def run(self):
print('pig is walking')
class Dog(Animal):
def run(self):
print('dog is running')
def func(animal):
animal.run()
func(Pig())
# pig is walking
2. self 是什么?
Python 的 self 相当于 C++ 的 this 指针。
class Test:
def prt(self):
print(self)
print(self.__class__)
t = Test()
t.prt()
# <__main__.Test object at 0x000000BC5A351208>
# <class '__main__.Test'>
class Ball:
def setName(self, name):
self.name = name
def kick(self):
print("我叫%s,该死的,谁踢我..." % self.name)
a = Ball()
a.setName("球A")
b = Ball()
b.setName("球B")
c = Ball()
c.setName("球C")
a.kick()
# 我叫球A,该死的,谁踢我...
b.kick()
# 我叫球B,该死的,谁踢我
3. Python 的魔法方法
class Ball:
def __init__(self, name):
self.name = name
def kick(self):
print("我叫%s,该死的,谁踢我..." % self.name)
a = Ball("球A")
b = Ball("球B")
c = Ball("球C")
a.kick()
# 我叫球A,该死的,谁踢我...
b.kick()
# 我叫球B,该死的,谁踢我...
4. 公有和私有
类的私有属性实例
class JustCounter:
__secretCount = 0 # 私有变量
publicCount = 0 # 公开变量
def count(self):
self.__secretCount += 1
self.publicCount += 1
print(self.__secretCount)
counter = JustCounter()
counter.count() # 1
counter.count() # 2
print(counter.publicCount) # 2
print(counter._JustCounter__secretCount) # 2 Python的私有为伪私有
print(counter.__secretCount)
# AttributeError: 'JustCounter' object has no attribute '__secretCount'
类的私有方法实例
5. 继承
class DerivedClassName(BaseClassName):
<statement-1>
.
.
.
<statement-N>
如果子类中定义与父类同名的方法或属性,则会自动覆盖父类对应的方法或属性。
class people:
# 定义基本属性
name = ''
age = 0
# 定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
# 定义构造方法
def __init__(self, n, a, w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" % (self.name, self.age))
# 单继承示例
class student(people):
grade = ''
def __init__(self, n, a, w, g):
# 调用父类的构函
people.__init__(self, n, a, w)
self.grade = g
# 覆写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级" % (self.name, self.age, self.grade))
s = student('小马的程序人生', 10, 60, 3)
s.speak()
# 小马的程序人生 说: 我 10 岁了,我在读 3 年级
注意:如果上面的程序去掉: people.__init__(self, n, a, w) ,则输
出: 说: 我 0 岁了,我在读 3 年级 ,因为子类的构造方法把父类的构造方法覆盖了。
【例子】
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):
self.hungry = True
def eat(self):
if self.hungry:
print("吃货的梦想就是天天有得吃!")
self.hungry = False
else:
print("太撑了,吃不下了!")
self.hungry = True
g = GoldFish()
g.move() # 我的位置 9 4
s = Shark()
s.eat() # 吃货的梦想就是天天有得吃!
s.move()
# AttributeError: 'Shark' object has no attribute 'x
使用super函数 super().init()
类属性和实例属性区别
- 类属性:类外面,可以通过 实例对象.类属性 和 类名.类属性 进行调用。类里面,通过 self.类属性
和 类名.类属性 进行调用。 - 实例属性 :类外面,可以通过 实例对象.实例属性 调用。类里面,通过 self.实例属性 调用。
- 实例属性就相当于局部变量。出了这个类或者这个类的实例对象,就没有作用了。
- 类属性就相当于类里面的全局变量,可以和这个类的所有实例对象共享。
习题
4.
15 魔法方法
魔法方法总是被双下划线包围,例如 init 。
魔法方法是面向对象的 Python 的一切,如果你不知道魔法方法,说明你还没能意识到面向对象的 Python 的强大。
魔法方法的“魔力”体现在它们总能够在适当的时候被自动调用。
魔法方法的第一个参数应为 cls (类方法) 或者 self (实例方法)。
1. cls :代表一个类的名称
2. self :代表一个实例对象的名称
1. 基本的魔法方法
init(self[, …])
- 构造器,当一个实例被创建的时候调用的初始化方法
new(cls[, …])
- new 是在一个对象实例化的时候所调用的第一个方法,在调用 init 初始化前,先调用 new 。
- new 至少要有一个参数 cls ,代表要实例化的类,此参数在实例化时由 Python 解释器自动提供,后面的
参数直接传递给 init 。 - new 对当前类进行了实例化,并将实例返回,传给 init 的 self 。但是,执行了 new ,并不
一定会进入 init ,只有 new 返回了,当前类 cls 的实例,当前类的 init 才会进入。
2. 算术运算符
-
add(self, other) 定义加法的行为: +
-
sub(self, other) 定义减法的行为: -
-
mul(self, other) 定义乘法的行为: *
-
truediv(self, other) 定义真除法的行为: /
-
floordiv(self, other) 定义整数除法的行为: //
-
mod(self, other) 定义取模算法的行为: %
-
divmod(self, other) 定义当被 divmod() 调用时的行为
-
divmod(a, b) 把除数和余数运算结果结合起来,返回一个包含商和余数的元组 (a // b, a % b) 。
-
pow(self, other[, module]) 定义当被 power() 调用或 ** 运算时的行为
-
lshift(self, other) 定义按位左移位的行为: <<
-
rshift(self, other) 定义按位右移位的行为: >>
-
and(self, other) 定义按位与操作的行为: &
-
xor(self, other) 定义按位异或操作的行为: ^
-
or(self, other) 定义按位或操作的行为: |
3. 反算术运算符
反运算魔方方法,与算术运算符保持一一对应,不同之处就是反运算的魔法方法多了一个“r”。当文件左操作不支持
相应的操作时被调用。
- radd(self, other) 定义加法的行为: +
- rsub(self, other) 定义减法的行为: -
- rmul(self, other) 定义乘法的行为: *
- rtruediv(self, other) 定义真除法的行为: /
- rfloordiv(self, other) 定义整数除法的行为: //
- rmod(self, other) 定义取模算法的行为: %
- rdivmod(self, other) 定义当被 divmod() 调用时的行为
- rpow(self, other[, module]) 定义当被 power() 调用或 ** 运算时的行为
- rlshift(self, other) 定义按位左移位的行为: <<
- rrshift(self, other) 定义按位右移位的行为: >>
- rand(self, other) 定义按位与操作的行为: &
- rxor(self, other) 定义按位异或操作的行为: ^
- ror(self, other) 定义按位或操作
行为: |
a + b
这里加数是 a ,被加数是 b ,因此是 a 主动,反运算就是如果 a 对象的 add() 方法没有实现或者不支持相应
的操作,那么 Python 就会调用 b 的 radd() 方法。
练习;
1.、利用python做一个简单的定时器类
要求:
- 定制一个计时器的类。
- start 和 stop 方法代表启动计时和停止计时。
- 假设计时器对象 t1 , print(t1) 和直接调用 t1 均显示结果。
- 当计时器未启动或已经停止计时时,调用 stop 方法会给予温馨的提示。
- 两个计时器对象可以进行相加: t1+t2 。
- 只能使用提供的有限资源完成。
import time
class Mytime(object):
def __init__(self):
self.__info = '未开始计时!'
self.__begin = None
self.__end = None
self.__jg = 0
def __str__(self):
return self.__info
def __repr__(self):
return self.__info
def start(self):
print('计时开始...')
self.__begin = time.localtime()
def stop(self):
if not self.__begin:
print('提示:请先调用start()开始计时!')
return
self.__end = time.localtime()
self.__jg = time.mktime(self.__end) - time.mktime(self.__begin)
self.__info = '共运行了%d秒' % self.__jg
print('计时结束!')
return self.__jg
def __add__(self, other):
return '共运行了%d秒' % (other.__jg + self.__jg)
t1 = Mytime()
print(t1)
# 未开始计时!
t1.stop()
# 提示:请先调用start()开始计时!
t1.start()
# 计时开始...
time.sleep(5)
t1.stop()
# 计时结束!
print(t1)
# 共运行了5秒
t2 = Mytime()
t2.start()
# 计时开始...
time.sleep(7)
t2.stop()
# 计时结束!
print(t2)
# 共运行了7秒
print(t1 + t2)
# 共运行了12秒