1 class Computer:   # 创建一个名为的类,注意类名首字母要大写!
2 
3     screen = True           # 用赋值语句,创建类的属性
4     def start(self):          # 创建类的方法,不要漏了 self
5         print('电脑正在开机中……')
6  
7 my_computer = Computer()   # 类的实例化
8 print(my_computer.screen)    # 实例调用类属性
9 my_computer.start()            # 调用类中的方法(传参不用管self)    

类中创建的属性和方法可以被其所有的实例调用,而且,实例的数目在理论上是无限的。我们可以同时“新建”多个实例

 1 class Chinese:
 2     eye = 'black'
 3 
 4     def eat(self):
 5         print('吃饭,选择用筷子。')
 6 
 7 # 类的实例化:创建多个实例
 8 wufeng = Chinese()
 9 jiangjiang = Chinese()
10 kaxi = Chinese()
11 
12 print(jiangjiang.eye)
13 wufeng.eat()
14 kaxi.eat()

运行结果

特殊参数:self

参数self的作用:self会接收实例化过程中传入的数据,当实例对象创建后,实例便会代替 self,在代码中运行。

换言之,self 是所有实例的替身,“替身”是什么意思呢?我们来看一个例子。

刚刚我们列举的类方法都只有一个self参数,实际上和一般函数一样,类的方法也可以设置多个参数:

 1 class Chinese:
 2 
 3     name = '吴枫'  # 类属性name
 4 
 5     def say(self, someone):  # 带有两个参数的方法
 6         print(someone + '是中国人')
 7 
 8 person = Chinese()
 9 print(person.name)
10 person.say('吴枫') 
11 # self调用时要忽略,'吴枫'传给参数someone

那么如果想在类的内部调用类属性,而实例又还没创建之前,我们就需要有个变量先代替实例接收数据,这个变量就是参数self。

 

1 class Chinese:
2 
3     name = '吴枫'  # 类属性name
4 
5     def say(self):     
6         print(self.name + '是中国人')
7 
8 person = Chinese()   # 创建Chinese的实例person
9 person.say()         # 调用实例方法

当最后一行代码运行时,实例person会像参数一样传给self,替换掉self,第六行的self.name等价于person.name

person.name就相当于调用了类属性name(即'吴枫'),然后跑完整个方法。

可见,self的作用相当于先给实例占了个位置,等到实例创建好就“功成身退,退位让贤”。

 同理,如果想在类的方法内部调用其他方法时,我们也需要用到self来代表实例。
 1 class Chinese:
 2 
 3     def greeting(self):
 4         print('很高兴遇见你')
 5 
 6     def say(self):
 7         self.greeting() 
 8         print('我来自中国')
 9 
10 person = Chinese()
11 # 创建实例person
12 person.say()
13 # 调用say()方法

运行结果为:

很高兴遇见你
我来自中国

最后一行实例person调用say()方法时,便会执行say()内部的语句(第七行开始)

此时self.greeting()就变成person.greeting(),也就是调用实例方法greeting(),打印出'很高兴遇见你',再打印出'我来自中国'。

综上,所以我们说self代表的是类的实例本身,方便数据的流转。对此,我们需要记住两点:

第一点:只要在类中用def创建方法时,就必须把第一个参数位置留给 self,并在调用方法时忽略它(不用给self传参)。

第二点:当在类的方法内部想调用类属性或其他方法时,就要采用self.属性名self.方法名的格式。

在self的基础上,下面我们来看第二个特殊点:初始化方法(也叫构造函数)

特殊方法:初始化方法
定义初始化方法的格式是def__init__(self),是由init加左右两边的【双】下划线组成( initialize “初始化”的缩写)。
初始化方法的作用在于:当每个实例对象创建时,该方法内的代码无须调用就会自动运行。
利用这个特性,在编写习惯上,我们会在初始化方法内部完成类属性的创建,为类属性设置初始值,这样类中的其他方法就能直接、随时调用。我们来看个例子:
 
除了设置固定常量,初始化方法同样可以接收其他参数,让传入的这些数据能作为属性在类的方法之间流转。我们再来看个例子:
 1 class Chinese:
 2 
 3     def __init__(self, name, birth, region):
 4         self.name = name   # self.name = '吴枫' 
 5         self.birth = birth  # self.birth = '广东'
 6         self.region = region  # self.region = '深圳'
 7 
 8     def born(self):
 9         print(self.name + '出生在' + self.birth)
10 
11     def live(self):
12         print(self.name + '居住在' + self.region)    
13 
14 person = Chinese('吴枫','广东','深圳') # 传入初始化方法的参数
15 person.born()
16 person.live()

 

先看14行:当初始化方法有多个参数的时候,在实例化的时候就要传入相应的值,这里'吴枫'传给参数name, '广东'传给birth,'深圳'传给region。
当实例person创建完成后,初始化方法会自动执行,此时第三行的self.name = name就等价于self.name = '吴枫',以此类推。(self.name中的name可以换成其他名称,只是我们习惯上这么写)
如此一来,类的其他方法就能通过self.属性名的形式调用传入的数据了。(还记得self是实例的替身吧)
我猜你可能会有这样的疑惑:不用初始化方法不是也能实现吗?写多个方法不是更麻烦吗?
确实可以,比如上述的代码,我们也可以这么写:
 1 class Chinese:
 2 
 3     def born(self, name, birthplace):
 4         print(name + '出生在' + birthplace)
 5 
 6     def live(self, name, region):
 7         print(name + '居住在' + region)
 8 
 9 person = Chinese()
10 person.born('吴枫','广东')
11 person.live('吴枫','深圳')

虽然代码量并没有减少,但我们可以看到使用初始化方法,至少我们不必重复传参,传入的数据还可以被多次调用,比如这里的'吴枫'。

随着我们想实现的功能愈发复杂,我们会在类内部编写很多的方法,如果我们需要传入的数据能在类中长久保存并能被随时调用,初始化方法就是一个不错的解决方案。

等你自己开始用类来写代码时,就会发现初始化方法又实在又好用。所以只要用到了类,一般都少不了它。

 

posted on 2019-09-14 23:12  乐无忧  阅读(506)  评论(0编辑  收藏  举报