一、面向对象基本概念
面向过程:根据业务逻辑从上到下写代码
面向对象:将变量与函数、属性绑定到一起,分类进行封装,每个程序只要负责分配给自己的功能,这样能够更快速的开发程序,减少了重复代码。
那什么是对象呢 ?我们可以理解为实际存在的实物,比如一个用户、一台ATM机、一幢建筑,亦或者是软件业务流程中产生的虚拟概念,比如订单、购物车、用户账户。我们发现,不管是实体还是虚拟产物,它们都是有一些共同点,都是名词,有自己的行为,有自己的属性。比如说用户对象,用户都有相 同的几个属性,名字、年龄、性别、注册时间、上一次登录的时间等等。但不同用户这几个属性的值却都不一样。
下面我们来看几个例子。如果你想向另一个人描述一只狗,那你会说出这只狗的哪几个特点
- 品种
- 颜色
- 体型大小
狗会有哪些行为
- 吃东西
- 奔跑
- 吠叫
这些都是我们基于常识总结出来的狗的特点和行为,对象的属性就是可以精确描述事物的特点,对象的函数就是事物的行为。
二、类和实列
类是创建对象的模板,对象是类的实例。定义一个类我们需要使用关键字class,类名一般用名词,且使用驼峰式命名法
class Dog:
pass
使用上面的Dog类来创建一个Dog对象:
dog = Dog()
type(dog)
这里dog就是Dog的实例,通过内置的type函数,可以查看任何对象的类。
三、对象的属性与方法
1、完整实现Dog类
class Dog:
def __init__(self):
self.breed = None
self.color = None
self.size = None
def eat(self):
print("I like bones")
def run(self):
print("I will catch you.")
def bark(self):
print("wang! wang!")
类的每一个方法的第一个参数是 self ,但在调用的时候却不需要传参数给它。它是类方法和普通函数的区别,这个self代表的是实例自身,意思是“我的”,
2、创建Dog的实例
dog = Dog()
dog.eat()
dog.run()
dog.bark()
print('一只%s型%s色的%s'% (dog.size, dog.color, dog.breed))
调用不同的方法能打印出不同的内容,体现了不同的行为。但是最后一句话打印出来的内容却是None,因为我们还没有设置相应的属性。
dog.breed = '哈士奇'
dog.color = '黑白'
dog.size = '大'
print('一只%s型%s色的%s' % (dog.size, dog.color, dog.breed))
# 一只大型黑白色的哈士奇
如果每个创建完每个对象之后还要一个个的设置属性,会很麻烦。我们可以使用 init 函数来接收初始化参数,这样就可以把属性的值作为参数在初始化对象的时候就传给它。它是Python的类用来初始化对象的构造函数,它的名字是固定的,必须这样写,创建对象时会首先调用它。改完后构造函数后代码如下:
class Dog:
def __init__(self,color,size,breed='土狗'):
self.breed = breed
self.color = color
self.size = size
def eat(self):
print("I like bones")
def run(self):
print("I will catch you.")
def bark(self):
print("wang! wang!")
重新创建对象
dog = Dog('中', '黄')
print('一只%s型%s色的%s' % (dog.size, dog.color, dog.breed))
对象自身的属性是直接可以方法里使用的,比如我们在Dog类加一个bark方法,这里在bark方法里使用的self和构造函数里的self一样,都是指向对象自身
class Dog:
def __init__(self,color,size,breed='土狗'):
self.breed = breed
self.color = color
self.size = size
def eat(self):
print("I like bones")
def run(self):
print("I will catch you.")
def bark(self):
print("wang! wang!")
def bark(self):
print('我是一只%s型%s色的%s' % (self.size, self.color, self.breed))
dog = Dog("小", "棕", "泰迪犬")
dog.bark()
四、类属性与方法
对象是从类创造的,对象的属性和方法虽然是在类中定义的,但它们的值是各个对象独有的,互相不能共享。而类也有属性和方法,且它们可以和类创建的所有对象共享。
我们来定义一个Goods类,并且给Goods类加一个计数器。
class Goods:
count = 0
def __init__(self):
Goods.count += 1
self.name = ''
self.price = 0
self.discount = 1
我们给Goods类加了一个属性count,每当调用 init 函数时将它加1,这样我们就可以知道一共创建了多少商品对象了。这个count就是类属性,它可以通过对象访问,也可以通过类访问。
goods = Goods()
goods.count ## 1
goods2 = Goods()
Goods.count ## 2
即使没有定义对象,也可以直接访问count属性,这就是类属性,同样,类方法也不需要创建对象,通过类名就可以访问。我们改造一下Goods类,给它增加一个属性id,表示商品唯一的序列号,为了保证id不重复,我们使用计数器,每创建一个商品给它加1。
class Goods:
id_count = 0
@classmethod
def generate_id(cls):
cls.id_count += 1
return cls.id_count
def __init__(self):
# zfill函数表示用“0”将数字补足5位
self.id = str(self.generate_id()).zfill(5)
self.name = ''
self.price = 0
self.discount = 1
这里的 generate_id 方法就是一个类方法,它的上面一行有一个 @classmethod ,声明了它是类方法,它的参数不再是self,而是cls,指向类本身,用来在类方法内部访问类成员属性和方法。这个方法每次将id_count属性加1,并返回。
g1 = Goods()
g2 = Goods()
g1.id # 00001
g2.id # 00002
Goods.id_count # 2
五、一切皆对象
在Python中一切都是对象,我们使用的数字、字符串、函数甚至类本身,都是对象。所有的对象都可以用type函数来判断它的类型,同时可以用dir函数来查看它的属性和方法。
dir(dog)
会显示出dog对象的所有属性和方法,包括刚刚定义的那几个方法和属性。对于对象,也可以使用help函数查看它的帮助文档。
help(sum)
help(print)
修改一下Dog类, 在brak方法加上我们的注释, 使用help函数展示
class Dog:
def __init__(self,color,size,breed='土狗'):
self.breed = breed
self.color = color
self.size = size
def eat(self):
print("I like bones")
def run(self):
print("I will catch you.")
def bark(self):
print("wang! wang!")
def bark(self):
"""一只狗的自我介绍"""
print('我是一只%s型%s色的%s' % (self.size, self.color, self.breed))
dog = Dog("小", "棕", "泰迪犬")
help(dog.bark)
help(Dog.bark)