对象 = 属性(变量)+ 方法(函数)
类和对象是什么关系呢?
solution:类和对象的关系就如同模具和用模具制造出来的物品之间的关系。一个类为它的全部对象给出了一个统一的定义,而它的每个对象则是符合这种定义的一个实体,因此类和对象的关系就是抽象和具体的关系。函数和方法有什么区别呢?
solution: 方法和函数其实几乎完全一样,但有一点区别是方法默认有一个 self 参数,这个参数的作用是绑定方法!当你调用方法时,对象会将自身作为第一个参数传给self,接收到这个self参数时,Python就知道这是哪个参数在调用方法啦~
面向对象(object oriented)的特征:
封装:对外部隐藏对象的工作细节。例如调用方法,只知道方法名称和功能,却不知道技术细节。
继承:子类自动共享父类之间数据和方法的机制。
class Mylist(list):
pass
这一步的操作就是让类Mylist继承了 list列表的方法。现在它可以使用列表里所有的内置方法。
list2 = Mylist()
list2,append(2)
继承父类的方法:(38讲)
class Derivedclass(Basename1, Basename2..)
当子类中定义了和父类一样名字的方法时,将会覆盖父类的方法,想要继续继承父类的方法时,使用'super.需要的父类方法名称'即可。
- 多态:可以对不同类的对象调用相同的方法,产生不同的结果。
class A:
def fun(self):
print('我是小A...')
class B:
def fun(self):
print('我是小B...')
a = A()
b = B()
a.fun()
我是小A...
b.fun()
我是小B...
- 当我们不希望对象的属性或方法被外部直接调用我们该怎么办呢?
solution:我们可以在属性或方法名字前面加双下划线。
>>> class Person:
__name = '小甲鱼'
def getName(self):
return self.__name
>>> p = Person()
>>> p.__name
Traceback (most recent call last):
File "<pyshell#56>", line 1, in <module>
p.__name
AttributeError: 'Person' object has no attribute '__name'
>>> p.getName()
'小甲鱼'
我们把getName方法称之为访问器,Python事实上是采用了一种叫 name mangling 的技术,将双下划线的变量名改了个名字而已,我们仍然可以通过外部'_类名__变量名'来访问
>>> p._Person__name'小甲鱼'
- 什么是组合?
Python 继承机制很有用,但容易把代码复杂化以及依赖隐含继承。因此,我们可以经常使用组合来代替继承。组合其实很简单,直接在类定义中把需要的类放进去实例化就可以了。
// 乌龟类
class Turtle:
def __init__(self, x):
self.num = x
// 鱼类
class Fish:
def __init__(self, x):
self.num = x
// 水池类
class Pool:
def __init__(self, x, y):
self.turtle = Turtle(x) // 组合乌龟类进来
self.fish = Fish(y) // 组合鱼类进来
def print_num(self):
print("水池里总共有乌龟 %d 只,小鱼 %d 条!" % (self.turtle.num, self.fish.num))
>>> pool = Pool(1, 10)
>>> pool.print_num()
- 类对象是在什么时候产生?
当你这个类定义完的时候,类定义就变成类对象,可以直接通过‘类名.属性’或‘类名.方法名()’引用,或使用相关的属性或方法。
一个简单的例子:定义一个矩形类并生成类实例对象。方法中对属性的引用形式需加上 self, 例如 self.width。
class Rectangle:
length = 5
width = 4
def setRect(self):
print("请输入矩形的长和宽...")
self.length = float(input('长:'))
self.width = float(input('宽:'))
def getRect(self):
print('这个矩形的长是:%.2f,宽是:%.2f' % (self.length, self.width))
def getArea(self):
return self.length * self.width
rect = Rectangle()
rect.setRect()
rect.getRect()
print(rect.getArea())
Python 的魔法方法
可以给类增加魔力的特殊方法!!一般被__双下划线所包围。
__init__(self,param1,param2)
构造方法
该魔法方法在对象被创建时会自动调用,当使用这个方法有了输入参数后,在实例化class的时候class()括号中也要传入参数了哦~~__init__ 方法不能返回除了None以外的任何对象!!
举个例子~定义一个游乐园门票的类~并计算两个成人一个小孩的平日票价~ 面向对象编程的难点在于思维的转换! 并不需要在里面把每一个都写的很详细,要通过不同的对象调用来实现统一的变化~
class Ticket():
def __init__(self, weekend=False, child=False):
self.exp = 100
if weekend:
self.inc = 1.2
else:
self.inc = 1
if child:
self.discount = 0.5
else:
self.discount = 1
def calcPrice(self, num):
return self.exp * self.inc * self.discount * num
>>> adult = Ticket()
>>> child = Ticket(child=True)
>>> print("2个成人 + 1个小孩平日票价为:%.2f" % (adult.calcPrice(2) + child.calcPrice(1)))
2个成人 + 1个小孩平日票价为:250.00
再举一个例子~定义一个栈(stack)类,用于模拟一种具有后进先出(LIFO)的数据结构。至少需要有以下方法。
class Stack:
def __init__(self, start=[]):
self.stack = []
for x in start:
self.push(x)
def isEmpty(self):
return not self.stack
def push(self, obj):
self.stack.append(obj)
def pop(self):
if not self.stack:
print('警告:栈为空!')
else:
return self.stack.pop()
def top(self):
if not self.stack:
print('警告:栈为空!')
else:
return self.stack[-1]
def bottom(self):
if not self.stack:
print('警告:栈为空!')
else:
return self.stack[0]