python2需要在类名后括号内写明父类,python3如果不写后面的括号,默认继承object
#class 类名(父类,没有就是object):
class Student(object):
pass
class Student(object):
pass
#实例变量名 = 类名()
stu = Student()
print(stu)
>>>>
#打印可以看到,实例属于S
<__main__.Student object at 0x000001538F0097F0>
由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的__init__
方法(构造方法),在创建实例的时候,就把属性绑上去
__init__
方法的第一个参数永远是self
,表示创建的实例本身,因此,在__init__
方法内部,就可以把各种属性绑定到self
,因为self
就指向创建的实例本身
class Student(object):
#构造方法
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
stu = Student('lucy',18,'女')
print(stu.name)
print(stu.age)
print(stu.sex)
要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__
,在Python中,实例的变量名如果以__
开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问
不能直接访问__name
是因为Python解释器对外把__name
变量改成了_Student__name
,所以,仍然可以通过stu._Student__name
来访问__name
变量,但是不要这么做
class Student(object):
#构造方法
def __init__(self,name,age,sex):
self.__name = name
self.__age = age
self.__sex = sex
stu = Student('lucy',18,'女')
要定义一个方法,除了第一个参数必须是self
外,其他和普通函数一样
class Student(object):
#默认值私有属性
__sex = '男'
#构造方法
def __init__(self,name,age,sex):
self.__name = name
self.__age = age
self.__sex = sex
def showMsg(self):
"展示学生信息"
print("姓名:",self.__name,"年龄:",self.__age,"性别:",self.__sex)
stu = Student('lucy',18,'女')
stu.showMsg()
私有方法和私有属性一样,在方法名前加两个下划线__
,方法就变成了私有的
私有方法同样可以通过stu._Student__sayHello()
进行访问,但是不要这么做
class Student(object):
#构造方法
def __init__(self,name,age,sex):
self.__name = name
self.__age = age
self.__sex = sex
def showMsg(self):
"展示学生信息"
print("姓名:",self.__name,"年龄:",self.__age,"性别:",self.__sex)
def sayHello(self):
"私有方法"
print('Hello')
stu = Student('lucy',18,'女')
stu.showMsg()
在类中直接定义的属性,就是静态属性,这个属性属于类,被该类所有实例共有
class Person(object):
name = 'lucy'
print(Person.name)
p = Person()
print(p.name)
'''
lucy
lucy
'''
python中,可以使用装饰器@classmethod
或@staticmethod
,
如果在@staticmethod中要调用到这个类的一些属性方法,只能直接类名.属性名或类名.方法名。
而@classmethod因为持有cls参数,可以来调用类的属性,类的方法,实例化对象等,避免硬编码。
class Person(object):
@staticmethod
def sayHello():
print('Hello World')
Person.sayHello()
p = Person()
p.sayHello()
'''
Hello World
Hello World
'''
在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)
可以使用isinstance(obj,class)
来查看对象obj是否属于类class
class Animal(object):
pass
#狗、猫类继承于动物类
class Dog(Animal):
pass
class Cat(Animal):
pass
#实例化
d = Dog()
c = Cat()
print(isinstance(d,Animal))
print(isinstance(c,Animal))
子类会继承父类中已经声明的属性,并且可以使用默认值
class Animal(object):
name = '动物'
#狗类继承于动物类
class Dog(Animal):
pass
#实例化
d = Dog()
#调用父类声明的属性
print(d.name)
子类会继承父类的所有方法,包括构造方法__init__()
class Animal(object):
def __init__(self,name):
self.__name = name
def run(self):
"动物都有的行为"
print('%s在跑' % self.__name)
#狗、猫类继承于动物类
class Dog(Animal):
pass
class Cat(Animal):
pass
#实例化,继承父类的构造方法
d = Dog("狗")
c = Cat("猫")
#继承父类的方法
d.run()
c.run()
如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法
class Animal(object):
def run(self):
print("动物在跑")
class Dog(Animal):
#重写父类方法run()
def run(self):
print("狗子在跑")
dog = Dog()
dog.run()
super() 函数是用于调用父类(超类)的一个方法,也就是使用子类对象,调用父类已被重写的方法
super() 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找顺序(MRO)、重复调用(钻石继承)等种种问题。
MRO就是类的方法解析顺序表, 其实也就是继承父类方法时的顺序表。
class Animal(object):
def run(self):
print("动物在跑")
class Dog(Animal):
#重写父类方法run()
def run(self):
print("狗子在跑")
dog = Dog()
dog.run()
#使用子类对象调用父类已经被重写的方法
super(Dog,dog).run()
python支持多继承,即可以继承于多个父类
需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索即方法在子类中未找到时,从左到右查找父类中是否包含方法
class Animal(object):
def run(self):
"动物都有的行为"
print('动物可以跑')
class Pet(object):
def play(self):
"宠物都有的行为"
print('宠物可以和主人玩')
class Cat(Animal,Pet):
pass
cat = Cat()
cat.play()
cat.run()
python不支持多态也用不到多态,多态的概念是应用于java和C#这一类强类型语言中,而Python崇尚鸭子类型(Duck Typing)
鸭子类型:是一种动态类型的风格。一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定。这个概念的名字来源于由James Whitcomb Riley提出的鸭子测试,“鸭子测试”可以这样表述:“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”
也就是说,我们可以编写一个函数,它接受一个类型为鸭的对象,并调用它的走和叫方法。在使用鸭子类型的语言中,这样的一个函数可以接受一个任意类型的对象,并调用它的走和叫方法。如果这些需要被调用的方法不存在,那么将引发一个运行时错误
class Duck(object):
def go(self):
print('鸭子走')
def run(self):
print('鸭子跑')
class Dog(object):
def go(self):
print('狗走')
def run(self):
print('狗跑')
#python的多态,不在于是哪个类,而是只要该对象有这两个方法就可以
def handler(duck):
duck.go()
duck.run()
duck = Duck()
dog = Dog()
handler(duck)
handler(dog)
type()可以获取对象的类型,返回一个Class类型的变量,可以使用==
判断两个对象是否同一类型
class Person(object):
def __init__(self,name,age):
self.__name = name
self.__age = age
def showMsg(self):
print('姓名',self.__name,'年龄',self.__age)
person = Person('lucy',18)
print(type(person)) # <class '__main__.Person'>
isinstance(obj,class)
来查看对象obj是否属于类class
class Person(object):
def __init__(self,name,age):
self.__name = name
self.__age = age
def showMsg(self):
print('姓名',self.__name,'年龄',self.__age)
person = Person('lucy',18)
print(isinstance(person,Person)) # Ture
如果要获得一个对象的所有属性和方法,可以使用dir()
函数,它返回一个包含字符串的list
class Person(object):
def __init__(self,name,age):
self.__name = name
self.__age = age
def showMsg(self):
print('姓名',self.__name,'年龄',self.__age)
person = Person('lucy',18)
print(dir(person))
'''
['_Person__age', '_Person__name', '__class__', '__delattr__',
'__dict__', '__dir__', '__doc__', '__eq__', '__format__',
'__ge__', '__getattribute__', '__gt__', '__hash__', '__init__',
'__init_subclass__', '__le__', '__lt__', '__module__', '__ne__',
'__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'__weakref__', 'showMsg']
'''
仅仅把属性和方法列出来是不够的,配合getattr()
、setattr()
以及hasattr()
,我们可以直接操作一个对象的状态,类似java的反射机制
获取对象某个属性的值
class Person(object):
def __init__(self,name,age):
self.__name = name
self.__age = age
def showMsg(self):
print('姓名',self.__name,'年龄',self.__age)
person = Person('lucy',18)
#获取person对象_Person__name属性的值
print(getattr(person,'_Person__name'))
#获取person对象_Person__name属性的值,如果不存在,返回404
print(getattr(person,'_Person__name',404))
设置对象某个属性的值
class Person(object):
def __init__(self,name,age):
self.__name = name
self.__age = age
def showMsg(self):
print('姓名',self.__name,'年龄',self.__age)
person = Person('lucy',18)
#设置person对象,_Person__name属性值为tom
setattr(person,'_Person__name','tom')
person.showMsg()
判断对象是否含有某个属性
class Person(object):
def __init__(self,name,age):
self.__name = name
self.__age = age
def showMsg(self):
print('姓名',self.__name,'年龄',self.__age)
person = Person('lucy',18)
#判断对象person中是否含有属性_Person__name
print(hasattr(person,'_Person__name'))
此外,这三个函数也可以作用于对象的方法
class Person(object):
def __init__(self,name,age):
self.__name = name
self.__age = age
def showMsg(self):
print('姓名',self.__name,'年龄',self.__age)
person = Person('lucy',18)
#判断对象person中是否含有方法showMsg
print(hasattr(person,'showMsg'))
#获取对象person的方法showMsg
show = getattr(person,'showMsg')
#调用方法
show() # 姓名 lucy 年龄 18