python 基础语法(11)
面向对象
概念
面向对象最重要的概念就是类和实例,类是实例的抽象,而实例是类的具象化。
定义类
- 类的关键字class(注意是小写)
- 类的名称(首字母大写)
- 继承的父类,所有类默认都继承于object,可以省略不写。
- 类的初始化函数 init(),在类实例化为对象时会默认调用该方法。
代码实例:
class User(object):
def __init__(self,id,sno,name,password):
self.id = id
self.sno = sno
self.name = name
self.password = password
类的方法
析构函数del()
与init()相对应,它会在删除对象或是系统回收对象时自动调用instance(obj, Employee)
用来判断obj是否为Emoloyee类型,但是判断不够准确,即当判断一个子类的实例时会返回True,当判断这个实例是否为它父类的实例时也会返回True。
继承
类的继承
- 在继承关系中,父类的构造方法(init())不会自动调用,它需要在其派生类的构造中亲自专门调用。
- 在调用类中的方法时,会首先在类中查找,找不到时在其父类中查找。
- python中没有方法的重载,后写的同名方法会覆盖之前的方法。
多重继承
两个类可以同时继承同一个类,一个类也可以同时继承多个类。
经典类的搜索方式是按照“从左至右,深度优先”的方式去查找属性
使用接口的思想设计多重继承
被继承的类主要分为类型类和功能类两种;
类型类实现主体继承树形结构,功能类作为独立的功能接口。
代码实例:
多重继承
class Animal(object):
def __init__(self,age):
self.age=age
# 大类:
class Mammal(Animal):
def __init__(self,age,foot):
super(Mammal,self).__init__(age)
self.foot=foot
class Bird(Animal):
def __init__(self,age,fly):
super(Bird,self).__init__(age)
self.fly=fly
class RunnableMixIn(object):
def run(self):
print('Running...')
class FlyableMixIn(object):
def fly(self):
print('Flying...')
# 各种动物:
class Dog(Mammal,RunnableMixIn):
def __init__(self,age,foot,gender):
super(Dog,self).__init__(age,foot)
self.gender=gender
def show(self):
print('dog age is:',self.age,'ang have ',self.foot)
dog=Dog(3,4,'male')
dog.show()
动态添加属性
在类实例化的时候,可以直接将实例化的对象.新属性,就可以为其动态添加属性,且不会影响到其它对象。
代码实例:
class Person:
pass
p1=Person()
p2=Person()
p1.gender='male'
print(p1.gender)
print(p2.gender) #'Person' object has no attribute 'gender'
动态为对象添加方法
这里会导入一个MethodType方法,通过该方法来实现方法的动态添加。
代码实例:
from types import MethodType
class Person:
pass
def displayMe(self):
print('my genderis:', self.gender)
# 给一个实例绑定的方法,对另一个实例是不起作用的:
p1.dispalyMe=MethodType(displayMe,p1)
p1.dispalyMe()
动态给类增加属性和方法
通过此手段,可以为所有对象都添加属性和方法。
类添加方法无需使用MethodType方法,直接像属性一样添加即可。
Person.gender='male'
def displayMe(self):
print('my genderis:', self.gender)
# 注意后面要加一个Person
Person.displayMe=displayMe(Person)
slots限制实例的属性
例如,只允许对Student实例添加name和age属性。
代码实例:
class Person(object):
__slots__=('name','age')
p1=Person()
print(dir(p1))
# 这是看到p1对象里已经存在name和age属性了
try:
p1.gender = 'female'
except Exception:
print('使用__slots__限制实例的属性')
删除属性
代码实例:
class Person:
def __init__(self):
self.age=1
p1=Person()
p2=Person()
p1.gender='male'
Person.nation='china'
del p1.gender
del p1.nation #error nation属于类的,不可以通过对象删除
del Person.nation
del p1.age #这是可以的
利用函数动态绑定
代码实例:
#该语句只能添加属性,不能添加方法
setattr(ee2, 'age', 8) # 添加属性 'age' 值为 8
getattr(ee1, 'age') # 返回 'age' 属性的值
hasattr(ee1, 'age') # 如果存在 'age' 属性返回 True。
delattr(ee1, 'age') # 删除属性 'age'
私有属性
1、 _xx 以单下划线开头的表示的是protected类型的变量。即保护类型只能允许其本身与子类进行访问。若内部变量标示,如: 当使用“from M import”时,不会将以一个下划线开头的对象引入 。
2、 __xx 双下划线的表示的是私有类型的变量。只能允许这个类本身进行访问了,连子类也不可以用于命名一个类属性(类变量),调用时名字被改变(在类FooBar内部,__boo变成_FooBar__boo,如self._FooBar__boo)
3、 xx定义的是特列方法。用户控制的命名空间内的变量或是属性,如init , import或是file 。只有当文档有说明时使用,不要自己定义这类变量。 (就是说这些是python内部定义的变量名)
python默认的成员函数和成员变量都是公开的,没有像其他类似语言的public,private等关键字修饰.但是可以在变量前面加上两个下划线"",这样的话函数或变量就变成私有的.这是python的私有变量轧压(这个翻译好拗口),英文是(private name mangling.) **情况就是当变量被标记为私有后,在变量的前端插入类名,再类名前添加一个下划线"",即形成了ClassName_变量名.
代码实例:
class pub():
# protected类型的变量和方法 在类的实例中可以获取和调用
_name = 'protected类型的变量'
__info = '私有类型的变量'
def _func(self):
print("这是一个protected类型的方法")
def __func2(self):
print('这是一个私有类型的方法')
# 如果想要在实例中获取到类的私有类形变量可以通过在类中声明普通方法,返回私有类形变量的方式获取
def get(self):
return(self.__info)
p=pub()
p.__info # error 因为__info是私有变量只有在类内部才可见,所以要用内部方法