[TOC]
<br>
### 类与实例的定义
>[info] 我们描述人类,动物时,很显然他们是不同的类,具有不同的特性,我们将具有相同特性的一类事务划到一个`类`型中。
而张三、李四,王五是人类中的一个具体的实例对象,他们具有人类的所有特性,但是他们又是不同的`实例`,例如他们的能力,外貌等各不相同。
类(Class)是面向对象程序设计(OOP,Object-Oriented Programming)实现信息封装的基础。**类是一种用户定义类型,也称类类型**。每个类包含数据说明和一组操作数据或传递消息的函数。类的实例称为对象。
类的构成包括**数据成员**和**成员函数**,数据成员对应类的属性,成员函数则用于操作类的各项属性,是一个类具有的特有的操作。
### python中的类与实例
类的定义:
```python
class Person(object):
""" 定义一个人类
人类具有属性:性别
人类具有行为能力:说话
"""
sex = "boy" # 类属性
def __init__(self, name):
""" 构造方法,在创建类实例时,初始化作用"""
self.name = name # 实例属性
def say_hello(self, language): # 实例方法
""" 自定义方法"""
result = {"name": self.name, "sex": self.sex, "language": language}
return result
```
类的使用:
```python
# 创建实例对象(一只具体的人),传入构造方法中规定的参数,初始化这个人的name属性值为sandy
p1 = Person("sandy")
print("p1:", p1) # 输出对象
print(p1.say_hello("普通话")) # 实例对象用'.'来调用类中的普通自定义方法
print("p1.sex:", p1.sex) # 实例对象用'.'来调用类中的普通属性
```
运行结果:
```cmd
p1: <__main__.Person object at 0x0000000000BED240>
{'name': 'sandy', 'language': '普通话', 'sex': 'boy'}
p1.sex: boy
```
***代码解释:***
这个实例,是最常用的一种类结构了。
1. 在python中,通过**关键字`class` 来声明类**,class后面跟着类名,这里定义了类"Person",类名后面的括号里面跟着该类的父类,这里的“object”是所有类的基类,这是一种新式类的写法,经典类中可以没有。建议都使用形式类吧,经典类就不提了。
2. 类中的方法,与之前学习的函数是否感觉特别相似?但是在类中,它叫方法,它的第一个参数固定是`self`,它表示**实例对象自身**,通过self.XXX 可以调用实例对象所拥有的属性和方法。
3. **实例,是通过类来创造的**。实例被创建后,就拥有了操作类属性和类方法的功能。
将类实例化,在java中需要`new`出来,而在python中,`类名([初始化参数])`就可以实例出一个对象了。创建实例时,首先就调用类中的构造方法\__init__,在\__init__中初始化一些需要外部传入的参数值给类属性。
### 属性
#### 类属性
是在声明类后,就存在与内存中,能够通过类来直接访问,如Person.sex
#### 实例属性
则只有在实例化后才会存在,如果直接通过类访问,如Person.name 则会报错:AttributeError: type object 'Person' has no attribute 'name'
#### 私有属性
在python中,有一种私有属性,命名时,以两个下划线开头,如下:
```python
class Person(object):
""" 定义一个人类
人类具有属性:性别
人类具有行为能力:说话
"""
sex = "boy" # 类属性
def __init__(self, name):
""" 构造方法,在创建类实例时,初始化作用"""
self.name = name
self.__age = 100 # 设置私有属性
def say_hello(self, language): # 自定义类方法
""" 自定义方法"""
result = {"name": self.name, "sex": self.sex, "language": language}
return result
def get_age(self):
return self.__age
```
编译的时候,私有属性__age自动加上类名,变成`_Person__membername`,这种技术叫变量名压缩(mangling),以达到外部不能调用的目的
**创建实例p1**
```cmd
p1 = Person('Sandy')
```
**调用私有属性__age:**
如果直接通过实例调用__age,如 p1.__age,则会报错:AttributeError: 'Person' object has no attribute '__age'
但是可以通过以下两种方式访问到__age,如
p1.get_age()
p1._Person__age
对于私有属性,我们一般都会通过第一种封装函数来访问。
### 方法
1. 方法是类内部定义的函数(意味着方法是类属性而不是实例属性)
2. ***方法只有在所属的类拥有实例时,才能被调用***,当存在一个实例时,方法才被认为是绑定到那个实例了
3. 任何一个方法定义中的第一个参数都是变量`self`,它表示调用此方法的实例对象。对于已绑定的方法调用来说,self是自动传递给这个方法的,在调用的时候就不需要传入这个参数了。
#### 静态方法@staticmethod与类方法@classmethod
>由前面的介绍可知,类中的方法,第一个参数都是self.
类中定义的方法,需要实例化后才能调用。
能否实现在方法中,不需要传入self,不需要实例化,直接通过类就能调用?
在python中,可以通过声明`静态方法`和`类方法`来实现。
**静态方法**:在类方法中,存在与类相关,但是又不需要改变类和实例状态的方法,这类方法可以声明为静态方法,静态方法不需要访问类里的任何参数。所带的参数都是从外部传入的。使用函数修饰符 @staticmethod 将方法声明为静态方法。
**类方法**:
python中使用函数修饰符@classmethod 将方法声明为类方法,可以被类直接调用。
类方法第一个参数必须是类属性,一般用cls,因此我们可以在方法里面调用类的属性、方法
```python
class Person(object):
""" 定义一个人类
人类具有属性:性别
人类具有行为能力:说话
"""
sex = "boy" # 类属性
def __init__(self, name):
""" 构造方法,在创建类实例时,初始化作用"""
self.name = name
def say_hello(self, language): # 类方法
""" 自定义方法"""
result = {"name": self.name, "sex": self.sex, "language": language}
return result
@staticmethod
def sing(song):
print("sing:", song)
@classmethod
def run(cls, distance):
print("run:", distance,"sex:",cls.sex)
```
调用方式:
```python
Person.sing("HIJKLMN...") # 类直接调用静态方法
Person.run("400") # 类直接调用类方法
Sandy=Person('Sandy')
Sandy.sing("ABCDEFG...") # 通过实例调用静态方法
Sandy.run("8000") # 通过实例调用类方法
```
运行结果:
```cmd
sing: HIJKLMN...
run: 400 sex: boy
sing: ABCDEFG...
run: 8000 sex: boy
```
#### 属性方法 @property
@property`把一个函数变成一个静态属性,直接调用函数名字`,不需要加括号,就能获取到函数返回值。一般用在不注重过程,只要结果的情况!
```python
class Person(object):
""" 定义一个人类
"""
sex = "boy" # 类属性
def __init__(self, name):
""" 构造方法,在创建类实例时,初始化作用"""
self.name = name
self.__age = 100
@property
def age(self):
return self.__age
Sandy = Person('Sandy')
print(Sandy.age) #不需要括号,看起来完全是一个属性,这就是属性方法
```
运行结果:
```cmd
100
```
### 类中内置的几个特殊方法
#### \__new__,\__init__,\__del__,\__str__
通过实例,了解他们的调用时机
```python
class Person(object):
""" 定义一个人类
"""
def __init__(self,name):
self.name=name
print("__init__ function call")
def __new__(cls, *args, **kwargs):
print("__new__ function call")
return super(Person, cls).__new__(cls)
def __del__(self):
print("__del__ function call")
def __str__(self):
print("__str__ function call")
return self.name
print("*"*30)
Sandy = Person('Sandy')
print("*"*30)
print(Sandy)
print("*"*30)
del Sandy
```
运行结果如:
```cmd
******************************
__new__ function call
__init__ function call
******************************
__str__ function call
Sandy
******************************
__del__ function call
```
\__new__() 是在新式类中新出现的方法,它作用在构造方法创建实例之前
\__init__() 构造方法,它作用于创建实例之时
\__str__() 作用于输出实例对象时
\__del__() 作用于销毁实例对象时
### 类的继承
在python中,object是新式类最顶级的类,是所有类的基类。
在前面的举例中,Person是人`类`,那么,“中国人”,“美国人”,“法国人”等也是`人类`中划分更细的一个群体,也可以定义成一个类,并且这些类具有`人类`的一切特征,但是又有属于自己特有的特征。
我们定义“中国人”,“美国人”类时,直接**继承**人类,即可实现在“中国人”和“美国人”这些`子类`中,无需重复编写相同的特性与属性,可以直接使用`父类`Person中定义的属性和方法。
#### 成员属性和方法的继承
```python
class Person(object):
""" 定义一个人类"""
sex = "Boy"
def say_hello(self, language): # 类方法
""" 自定义方法"""
print("Lanuage:", language)
class Chiness(Person):
""" 定义中国人 类"""
nature = "Love Peace!"
p1 = Chiness()
print(p1.sex) # 从子类中,可以调用父类的成员数据
p1.say_hello("普通话") # 从子类中,可以调用父类的方法
```
运行结果:
```cmd
Boy
Lanuage: 普通话
```
#### 子类对父类方法的重写
子类的的方法如果和父类的方法重名,子类会覆盖掉父类。
```python
class Person(object):
""" 定义一个人类"""
sex = "Boy"
def say_hello(self, language): # 类方法
""" 自定义方法"""
print("Lanuage:", language)
class Chiness(Person):
""" 定义中国人 类"""
nature = "Love Peace!"
def say_hello(self,language):
print("您好,我是中国人,我的母语是",language)
p1 = Chiness()
p1.say_hello("普通话") # 从子类中,调用父类的方法
```
在Chiness类中,具有与父类方法名相同的say_hello,当Chiness的实例对象调用say_hello时,就会使用Chiness中的say_hello。
运行结果:
```cmd
您好,我是中国人,我的母语是 普通话
```
#### 构造方法的继承与重写
一般来说,子类的构造方法都是先继承,然后扩展。其中,
**新式类**的构造方法继承写法如:***`supper(子类,self).__init__(参数1,参数2...)`***
**经典类**的构造方法继承写法如:*父类名称.\__init__(self,参数1,参数2,...)*
```python
class Person(object):
""" 定义一个人类"""
sex = "Boy"
def __init__(self, name):
self.name = name
def say_hello(self): # 类方法
""" 自定义方法"""
print("name:", self.name)
class Chiness(Person):
""" 定义中国人 类"""
def __init__(self, name, nature):
super(Chiness, self).__init__(name) # 先继承父类的构造方法
self.nature = nature # 扩展子类的构造方法
def say_hello(self):
print("您好,我是中国人,我的名字是【{name}】,我的天性是【{nature}】".format(name=self.name, nature=self.nature))
p1 = Chiness("张三", "爱好和平")
p1.say_hello()
```
运行结果:
```cmd
您好,我是中国人,我的名字是【张三】,我的天性是【爱好和平】
```
### 多态
>子类的的方法如果和父类的方法重名,子类会覆盖掉父类。因为这个特性,就获得了一个继承的好处”多态”。
```python
class Person(object):
""" 定义一个人类"""
def __init__(self, name):
self.name = name
def say_hello(self): # 类方法
""" 自定义方法"""
print("name:", self.name)
class Chiness(Person):
""" 定义中国人 类"""
def __init__(self, name, nature):
super(Chiness, self).__init__(name) # 先继承父类的构造方法
self.nature = nature # 扩展子类的构造方法
def say_hello(self):
print("您好,我是中国人,我的名字是【{name}】,我的天性是【{nature}】".format(name=self.name, nature=self.nature))
class America(Person):
""" 定义一个美国人 类"""
def __init__(self, name, nature):
super(America, self).__init__(name) # 先继承父类的构造方法
self.nature = nature # 扩展子类的构造方法
def say_hello(self):
print("Hello,I am America,My name is 【{name}】,my nature is 【{nature}】".format(name=self.name, nature=self.nature))
def say_hello(people):
people.say_hello()
p1 = Chiness("张三", "爱好和平")
p2 = America("Perter","fighting")
# 同一个方法,传入不同的人,会说出不同的问候,这便是一种多态...
say_hello(p1)
say_hello(p2)
```
运行结果:
```cmd
您好,我是中国人,我的名字是【张三】,我的天性是【爱好和平】
Hello,I am America,My name is 【Perter】,my nature is 【fighting】
```
<hr style="margin-top:100px">
:-: ![](https://box.kancloud.cn/2ff0bc02ec938fef8b6dd7b7f16ee11d_258x258.jpg)
***微信扫一扫,关注“python测试开发圈”,了解更多测试教程!***
- 前言
- chapter01_开发环境
- chapter02_字符串的使用
- chapter03_列表的使用
- chapter04_字典的使用
- chapter05_数字的使用
- chapter06_元组的使用
- chapter07_集合的使用
- chapter08_输入输出
- chapter09_控制流程
- chapter10_实例练习_登录1
- chapter11_python函数入门
- chapter12_python中的类
- chapter13_轻松玩转python中的模块管理
- chapter14_掌握学习新模块的技巧
- chapter15_通过os模块与操作系统交互
- chapter16_子进程相关模块(subprocess)
- chapter17_时间相关模块(time & datetime)
- chapter18_序列化模块(json)
- chapter19_加密模块(hashlib)
- chapter20_文件的读与写
- chapter21_阶段考核2_登录
- chapter22_小小算法挑战(排序&二分法)
- chapter23_用多线程来搞事!
- chapter24_HTTP接口请求(requests)
- chapter25_接口测试框架(pytest)
- chapter26_阶段考核3_HTTP接口测试
- chapter27_HTML解析(pyquery)
- chapter28_阶段考核4_爬虫下载网易汽车
- chapter29_python中的那些编码坑
- chapter30_MySQL数据库操作
- chapter31 高级特性_迭代器与生成器
- chapter32 高级特性_装饰器
- chapter33 高级特性_列表处理