单身狗小心了,本章进入面向对象编程。
Class称为类,Object称为对象,类的实例称为对象。
创建和使用Class
看一个简单定义:
class User:
def __init__(self, name, age):
self.name = name;
self.age = age;
def get_name(self):
print(f"Name is {self.name}.")
def get_age(self):
print(f"Age is {self.age}.")
user1 = User('tom', 20)
user1.get_name()
user1.get_age()
print(f"name is {user1.name}, age is {user1.age}.")
user1.age = 100
print(f"name is {user1.name}, age is {user1.age}.")
__init__
是Class的初始化方法,只能有一个。
Class中所有方法都必须至少有一个参数,这个参数而且必须是第一个参数,指向本对象。
换句话说,当调用方法时,Class都会将指向对象的指针作为第一个参数传入方法。在本例中,即self
,这类似于Java中的this
。但self
并非关键字,你可以换成别的变量名,不过无论如何,它都指向本对象。
name和age都是此Class的属性,Class的属性可以直接访问和修改,这点倒是和Java不同。Python并没有public
和·private`属性之分。
Class和实例
关于属性的默认值,可以在参数部分不包括此属性,然后在方法主体中直接设置此属性即可。
也可以在参数列表中指定默认值:
def __init__(self, status=True):
前面已经说过,对象的属性可以通过方法访问(如果需要复杂的规则),也可以直接用对象名+.
访问。
对象可以作为函数的参数,而且和List和Dictionary一样,是传递reference的,因此可以在函数体内修改:
$ cat user.py
class User:
def __init__(self, name, age):
self.name = name;
self.age = age;
def print_user(user):
print(f"name: {user.name}, age:{user.age}")
def add_age(user):
user.age += 1
user1 = User("tom", 18)
print_user(user1)
add_age(user1)
print_user(user1)
$ python3 user.py
name: tom, age:18
name: tom, age:19
继承
子类继承父类的所有属性和方法,子类可以定义自己的属性和方法。
$ cat superuser.py
class User:
def __init__(self, name, age):
self.name = name;
self.age = age;
def get_name(self):
print(f"Name is {self.name}.")
def get_age(self):
print(f"Age is {self.age}.")
class SuperUser(User):
def __init__(self, name, age, isvip):
super().__init__(name, age)
self.isvip = True
def is_vip(self):
print(f"user {self.name} is VIP.")
s = SuperUser('amy', 16, True)
s.get_name()
s.get_age()
s.is_vip()
$
$ python3 superuser.py
Name is amy.
Age is 16.
user amy is VIP.
父类和子类的定义必须在同一文件,并且父类的定义必须在前。
定义子类时,父类的名字必须在括号中,例如class SuperUser(User)
。
子类通过super()
可以调用父类中的方法,通常需要调用父类的初始化方法,如super().__init__(name, age)
。如果不调用的化,就必须自己做初始化。
父类中的方法在子类中可以覆盖(override),也就是方法名和参数个数相同:
class SuperUser(User):
...
def get_name(self):
print(f"Name is VIP:{self.name}.")
...
此外,重载(overload,指方法名一样,参数不一样)也是支持的,例如:
...
def get_name(self, comment):
super().get_name()
print(f"Name is VIP:{self.name}.")
print(comment)
...
对象可以作为对象的属性。
导入Class
和函数一样,Class也可以在单独文件中定义,然后利用import
导入,形式如下。
from module import class1, class2, ..., classN
和函数一样,以下导入所有函数的写法不建议:
from module import *
可以加别名:
from super_man import SuperMan as SM
示例:
$ cat user.py
class User:
def __init__(self, name, age):
self.name = name;
self.age = age;
def get_name(self):
print(f"Name is {self.name}.")
def get_age(self):
print(f"Age is {self.age}.")
$ cat superuser.py
from user import User
class SuperUser(User):
def __init__(self, name, age, isvip):
super().__init__(name, age)
self.isvip = True
def get_name(self):
print(f"Name is VIP:{self.name}.")
def is_vip(self):
print(f"user {self.name} is VIP.")
s = SuperUser('amy', 16, True)
s.get_name()
$ python3 superuser.py
Name is VIP:amy.
如果导入的Class较多,也可以导入整个module:
import module
此时在调用Class时就需要加上模块名,例如module.ClassName
。
Python标准库
指包含在安装中的module,通过import就可以使用。
例如:
>>> from random import randint
>>> randint(1,100)
88
或者:
>>> import random
>>> random.randint(1, 100)
66
>>> randinit(1, 100)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'randinit' is not defined
另一个示例:
>>> from random import choice
>>> suits = ['heart', 'diamond', 'club', 'spade']
>>> selected = choice(suits)
>>> selected
'spade'
Class风格
Class的名称遵循CamelCase
,类似于驼峰,每个单词的首字母大写,并且不含大小写,例如SuperMan
。
实例和module的名字应小写,单词间用下划线_
分割。
和函数和方法一样,Class和module都应包括docstring
描述。
在Class内部,用单空行分隔方法。
在module内部,用双空行分隔Class。
需要引入标准库时,import语句放在文件首,然后下接空行,再import自己写的库。