python学习(三)面向对象

python面向对象

继承

class Person(object):
    '''
    classdocs
    '''
    def __init__(self,name):
        '''
        Constructor
        '''
        self.name = name



class Student(Person):

    def __init__(self,age,score):
        self.age = age
        self.score = score

    def printInfo(self):
        print("name is :%s  age is :%s score is :%s" %(self.name, self.age,self.score))

student = Student(22,89)
student.name = "test"
student.printInfo()

以上Person类继承自object,并且有一个name属性,Student类继承自Person,定义了一个printInfo方法,用来打印信息,此时运行效果如下:
这里写图片描述

私有属性

在python中,给变量名称前面增加两个下划线,表示该变量是一个私有的变量

class Student(Person):

    def __init__(self,age,score):
        self.__age = age
        self.score = score

    def printInfo(self):
        print("name is :%s  age is :%s score is :%s" %(self.name, self.age,self.score))

上面age表示私有属性,不能通过对象来设置值,只能在类内部操作

为私有变量设置get和set方法

class Student(Person):

    def __init__(self,age,score):
        self.__age = age
        self.__score = score

    def printInfo(self):
        print("name is :%s  age is :%s score is :%s" %(self.name, self.__age,self.__score))

    def set_age(self,age):
        self.__age = age
    def get_age(self):
        return self.__age

student = Student(22,89)
student.name = "test"
student.set_age(30)
student.printInfo()
print("age is :%s" %(student.get_age()))

这里写图片描述

其实对于私有变量,也不是一定必须要通过get方法来获取,对于上面的栗子,python解释器将其解释成了_Student__age,所以,我们依然可以通过这个属性来访问

print("age is :%s" %(student._Student__age)) # 输出: age is :30

需要注意下面问题

上面我们通过self.__age = age 将age属性表示为私有属性,但是有的同学发现好像还是可以通过下面的代码来设置的

student.age = 12

其实这个是不对的,前面已经说过了,对于私有属性__age,python解释器将其解释为_Student__age,上面的代码,就相当于为student对象的name属性赋值

获取对象信息

可以使用type函数获取当前对象的类型

print type(Student(22,50))
print type(23)
print type("string")
print type(22.0)

这里写图片描述

判断是否是某个类的实例

python中同样提供了isinstance函数来判断一个对象是否是一个类的实例

print isinstance(Student(22,88),Person)  #输出: True

hasattr和setattr

python中提供了setattr来为对象设置一个新的属性,hasattr判断是否有一个指定的属性


student = Student(22,88)
print hasattr(student,"score")

setattr(student,"year","1990")  # 输出 True

print student.year  # 输出 1990

类属性

上面的所有属性都是通过self或者对象本身创建的属性,这些都是对象属性,那么同样在python中可以创建一个类似于java中的static属性,我们称之为类属性

class Student(Person):

    password = "Student pass"


print("类属性 password is :%s" %(Student.password))  # 输出: 类属性 password is :Student pass
Student.password = "a new pass"
print("类属性 password is :%s" %(Student.password))   # 输出: 类属性 password is :a new pass

实例属性的优先级高于类属性

给实例绑定方法

from types import MethodType        
class Student(object):

    password = "Student pass"

    def __init__(self,age,score):
        self.age = age
        self.score = score

    def printInfo(self):
        print("age is :%s score is :%s" %(self.age,self.score))


def set_age(self,age):
    self.age = age

student = Student(22,88)
student.name = "王五"
student.printInfo()
# 使用MethodType为实例绑定方法,注意需要引入对应的模块
student.set_age = MethodType(set_age,student);
student.set_age(44)

student.printInfo()

上面使用MethodType虽然可以为实例绑定一个方法,但是这个方法对于另外一个实例是没有效果的,比如:如果我们重新创建一个实例,并且执行上一步绑定的方法,此时会抛出如下错误:

studentSecond = Student(23,88)
studentSecond.set_age(44)

这里写图片描述

为了解决上面的问题,我们可以给整个class绑定方法,这样该类的所有实例都可以访问这样的方法了

def set_age(self,age):
    self.age = age

Student.set_age = set_age

student = Student(22,88)
student.name = "王五"
student.printInfo()

student.set_age = MethodType(set_age,student);
student.set_age(44)

student.printInfo()

studentSecond = Student(23,88)
studentSecond.set_age(55)
studentSecond.printInfo()

限制类绑定的属性

# 我们可以使用__slots__在当前类中声明属性,这样的话,当前类的所有实例就只能绑定声明中已有的属性

class Person(object):
    '''
    classdocs
    '''
    def __init__(self,name):
        '''
        Constructor
        '''
        self.name = name


class Student(object):

    __slots__ = ["age","score"]

    def printInfo(self):
        print("age is :%s score is :%s" %(self.age,self.score))


student = Student()
student.age = 22
student.score = 33
# 试图绑定name属性
student.name = "wangwu"
student.printInfo()

这里写图片描述

可以看到这里,我们限定当前类只能绑定age和score属性,此时当程序试图绑定name属性的时候,就会出现错误

需要注意的是绑定属性对于当前类的子类是没有效果的,看下面栗子

class SubStudent(Student):
    pass

subStudent = SubStudent()
subStudent.age = 33
subStudent.score = 55
subStudent.name = "xiaolizi"
subStudent.printInfo()
print subStudent.name

把方法变成属性

我们可以通过”@property”

class Student(object):

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self,value):
        self._age= value


    def printInfo(self):
        print("age is :%s score is :%s" %(self.age,self.score))

student = Student()
student.age = 55
print student.age  # 输出: 55

python多继承

另外在python中是支持多继承的,看下面的栗子

class Person(object):
    '''
    classdocs
    '''
    def __init__(self,name):
        '''
        Constructor
        '''
        self.name = name


class MusicTeacher(Person):

    def learnMusic(self):
        print "student need to learn music"

class MathTeacher(Person):

    def learnMath(self):
        print "student need to learn math"

class Student(MusicTeacher,MathTeacher):

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self,value):
        self._age= value


    def printInfo(self):
        print("name is :%s age is :%s" %(self.name,self.age))

student = Student("张三")
student.age = 55
student.printInfo()
student.learnMath()
student.learnMusic()

学生会学习音乐和数学这两门课程,此时运行效果如下:
这里写图片描述

重写”toString”

这里之所以给”toString”添加上双引号,是因为这里实际并不是一个toString方法,看下面栗子

class Student(MusicTeacher,MathTeacher):

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self,value):
        self._age= value

student = Student("张三")
student.age = 55
print student

这里此时打印如下:
这里写图片描述
可以看到,这里和java中一样,打印的是student实例的内存地址,不过我们可以通过添加像java中的toString方法

def __str__(self):
        return "student name is :"+self.name 

此时效果如下:
这里写图片描述

对实例进行调用

另外,在python中可以直接调用对象,只需要为当前类添加如下方法的实现即可:

__call__()

看下面栗子:

class Student(MusicTeacher,MathTeacher):

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self,value):
        self._age= value

    def __call__(self):
        print "This is student self call...."

student = Student("张三")
student.age = 55
student()

这里写图片描述

枚举实现

在python中,同样支持枚举类型,在3.6上直接支持,我的是在2.7上的实现,看下面栗子

def enum(**enums):
    return type('Enum', (), enums)

Weeks = enum(MONDY=1, TUESDAY=2, WENSDAY='three')
print str(Weeks.MONDY)+"   "+str(Weeks.TUESDAY)+"    "+Weeks.WENSDAY

这里写图片描述

动态创建一个类

在python中,可以通过type动态创建一个类,看下面栗子

def sayHello(self):
    print "hello world"

Hello = type('Hello', (object,), dict(sayHello=sayHello)) # 创建Hello class
hello = Hello()
hello.sayHello()  # 输出: hello world

python中常见的特殊函数

python中的特殊方法,有如下特点:

  • 特殊方法定义在class中
  • 不需要直接调用
  • python的某些函数或操作符会调用对应的特殊方法
  • 在实现某一个特殊方法的时候,关联的特殊方法必须同时实现

在之前的学习中,我们每次打印一个对象,比如list

class Person(object):

    def __init__(self,name):
        self.name = name

person = Person("王五")
print person

b = ["alice","tom","jerry","xiaoming"]
print b

这里写图片描述

这是因为任何一个数据类型都有一个下面的方法

"__str__()"

上面的操作其实就等同于

person = Person("王五")
print person.__str__()

b = ["alice","tom","jerry","xiaoming"]
print b.__str__()
获取类的特殊方法

在python中,可以通过dir方法来获取某一类对象所拥有的特殊方法

print dir(person)

['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'name']
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值