python面向对象

1、创建类、类的构造函数、类变量 、类方法、创建类的对象,调用类的方法和类变量 :

class Employee:   #定义Employee类

    empCount=0    #类变量,可以使用Employee.empCount访问

    def __init__(self,name,salary):  #Employee类的构造函数
        self.name=name
        self.salary=salary
        Employee.empCount+=1

    def displayCount(self):   #实例方法,实例方法都带有self参数,调用时不用传入
        print("Total Employee %d"%Employee.empCount)

    def displayEmployee(self):
        print("Name:",self.name,",Salary:",self.salary)


emp=Employee('Zara',4000)     #创建类的实例对象
emp.displayCount()
emp.displayEmployee()
print ("Total Employee: %d"%Employee.empCount)

运行结果:

Total Employee 1
Name: Zara ,Salary: 4000
Total Employee: 1

class Animal(object):


    def __init__(self,age,sex,weight):
        # 实例变量
        self.age=age
        self.sex=sex
        self.__weight=weight #私有变量在类中访问没有问题


    def eat(self):   #实例方法
        self.__weight+=0.05
        print('eat can add 0,05')

    def run(self):#实例方法
        self.__weight-=0.05
        print('eat can ...')

anim=Animal(2,'femal',23)
print(anim.age,anim.sex,anim._Animal__weight)  #私有变量在类外面的访问方法:_类名__私有变量名
anim.eat()
anim.run()


class Account:

    #类变量,属于类,在java中叫静态变量,调用:类名.类变量名
    interest_rate=0.0668

    def __init__(self,owner,amout):
        # 实例变量
        self.owner=owner
        self.amout=amout

    #类方法,可以访问其他的类方法和类变量,不能访问实例变量和实例方法
    @classmethod  #@表示装饰器
    def interest_by(cls,amt):  #cls表示当前类,类方法不需要和实例绑定,要与当前类绑定,第一个参数是type类型,type是描述数据类型的类
        print(type(cls))
        return cls.interest_rate *amt  #cls.interest_rate和Account.interest_rate

    #实例方法
    def jisuan(self):  #self表示当前实例与该方法绑定在一起了
        print('我是实例方法')


    #静态方法,不用与类绑定,可以调用类变量,类方法,
    @staticmethod
    def interest_with(amt):
        return Account.interest_by(amt)



account=Account('Navy',1000)
print(account.owner,account.amout)
account.jisuan()
print(account.interest_rate)  #先到当前实例中去找,没找到去类中找
print(account.__dict__ ) #查看这个实例中的变量
account.interest_rate=0.00555  #相当于给实例增加了一个实例变量,可以通过这种方法创建实例变量,但是使用的人不知道,写在构造方法中更明白,
account.interest_rate1=0.00555#这样创建的实例变量,重新创建实例是没有的,只有构造方法中的实例变量才能同步到每个实例中
print(account.__dict__ )

print(Account.interest_rate)  #类变量还是0.0668
print(account.interest_rate)  #增加了一个实例变量0.00555

print(Account.interest_by(2000) ) #调用类方法:类名.类方法
print(Account.interest_with(3000))#掉用静态方法:类名.静态方法

执行结果:

2 femal 23
eat can add 0,05
eat can ...
Navy 1000
我是实例方法
0.0668
{'owner': 'Navy', 'amout': 1000}
{'owner': 'Navy', 'amout': 1000, 'interest_rate': 0.00555, 'interest_rate1': 0.00555}
0.0668
0.00555
<class 'type'>
133.6
<class 'type'>
200.4

2、类的继承:

(1)

class Parent:  #父类
    parentAttr=100

    def __init__(self):
        print("父类的构造函数")

    def parentMethod(self):
        print("父类方法")
    def setAttr(self,attr):
        Parent.parentAttr=attr
    def getAttr(self):
        print("父类属性:",Parent.parentAttr)


class Child(Parent):  #Child子类继承Parent父类
    def __init__(self):
        print("子类构造函数")

    def childMethod(self):
        print("子类方法")

c = Child()          # 实例化子类
c.childMethod()      # 调用子类的方法
c.parentMethod()     # 调用父类方法
c.setAttr(200)       # 再次调用父类的方法 - 设置属性值
c.getAttr()          # 再次调用父类的方法 - 获取属性值

运行结果:

子类构造函数
子类方法
父类方法
父类属性: 200

(2)多重继承的执行顺序:

class people:
    name=''
    age=0
    _weight=0   #可以被类及其子类访问

    def __init__(self,n,a,w):
        self.name=n
        self.age=a
        self._weight=w
    def speak(self):
        print('%s 说:我 %d 岁,体重 %d 千克。'%(self.name,self.age,self._weight))

n=people('navy',15,50)
n.speak() #navy 说:我 15 岁,体重 50 千克。

class student(people):
    grade=''
    def __init__(self,n,a,w,g):
        people.__init__(self,n,a,w)
        self.grade=g
    def speak(self):
        print('%s 说:我 %d 岁,,体重 %d 千克,现在上%d年级' % (self.name, self.age,self._weight,self.grade))#,体重 %d 千克
m=student('Luc',15,36,5)
m.speak()#Luc 说:我 15 岁,,体重 36 千克现在上5年级

class speaker():
    topic=''
    name=''
    def __init__(self,n,t):
        self.nam=n
        self.topic=t
    def speak(self):
        print("我叫%s,我是一个演说家,我演讲的主题是%s"%(self.name,self.topic))


class smple(speaker,student):
    a=''
    def __init__(self,n,a,w,g,t):
        student.__init__(self,n,a,w,g)
        speaker.__init__(self,n,t)

test=smple('Tim',25,45,4,'python')
test.speak()  #我叫Tim,我是一个演说家,我演讲的主题是python(调用的是speaker类中的speak()方法)

class smple2(student,speaker):
    a=''
    def __init__(self,n,a,w,g,t):
        student.__init__(self,n,a,w,g)
        speaker.__init__(self,n,t)
test2=smple2('Tim',25,45,4,'python')
test2.speak()  #Tim 说:我 25 岁,,体重 45 千克现在上4年级(调用的是student类中的speak()方法)

3、python中方法的重写和重载

先来看看概念:

重写:方法的名称和参数都必须相同,存在继承中,子类的构造函数就是对父类的构造函数的重写,还有其它同名同参数的方法

重载:方法名称相同,但是参数列表不相同(类型不同,数量不同,位置不同),python是动态语言,参数不需要申明

python的实现过程中可能存在重载,但是在Python的呈现使用中不存在重载的概念。

原因:python 可以接受任何类型的参数,而对那些缺少的参数设定为缺省参数即可解决问题。即,python中参数传递时候的*arg和**kwargs

4、单双下划下开头方法和变量

__foo__:以双下划线开头和结尾的方法称为魔法方法,魔法方法可以直接访问,如:__init__,__new__等之类的

_foo:以单下划线开头的表示是protected类型的变量,即保护类型只能允许其本身及其子类进行访问,不能用于from module import *

__foo:以双下划线开头的表示是private的变量,只能允许这个类本身进行访问

private变量的例子:

class people:
    name=''
    age=0
    __weight=0

    def __init__(self,n,a,w):
        self.name=n
        self.age=a
        self.__weight=w
    def speak(self):
        print('%s 说:我 %d 岁,体重 %d 千克。'%(self.name,self.age,self.__weight))

n=people('navy',15,50)
n.speak()    #navy 说:我 15 岁,体重 50 千克。

class student(people):
    grade=''
    def __init__(self,n,a,w,g):
        people.__init__(self,n,a,w)
        self.grade=g
    def speak(self):
        print('%s 说:我 %d 岁,,体重 %d 千克现在上%d年级' % (self.name, self.age,self.__weight,self.grade))#,体重 %d 千克
m=student('Luc',15,36,5)
m.speak()  #报错:AttributeError: 'student' object has no attribute '_student__weight'

面向对象高级编程:

1、__slots__

正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性

class Student(object):
    pass

#然后,尝试给实例绑定一个属性:

s=Student()
s.name='Michael'
print(s.name)   #Michael

#还可以尝试给实例绑定一个方法:

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

from types import MethodType
s.set_age=MethodType(set_age,s)
s.set_age(25)
print(s.age)   #25


#但是,给一个实例绑定的方法,对另一个实例是不起作用的:
s2=Student()
s2.set_age(26)  #报错:AttributeError: 'Student' object has no attribute 'set_age'




#为了给所有实例都绑定方法,可以给class绑定方法:

class Student(object):
    pass

s=Student()
s2=Student()

def set_score(self,score):
    self.score=score

Student.set_score=set_score


s.set_score(100)
print(s.score)


s2.set_score(99)
print(s2.score)

如果我们想要限制实例的属性怎么办?比如,只允许对Student实例添加nameage属性。

为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性:

class Student(object):
    __slots__ = ('name','age')

s=Student()
s.name='Michael'
s.age=25
#s.score=99   #报错,AttributeError: 'Student' object has no attribute 'score'
print(s.name,s.age)

由于'score'没有被放到__slots__中,所以不能绑定score属性

使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的,除非在子类中也定义__slots__,这样,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__

2、@property

在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改:

class Student():
    pass

s=Student()
s.score=9999

这显然不合逻辑。为了限制score的范围,可以通过一个set_score()方法来设置成绩,再通过一个get_score()来获取成绩,这样,在set_score()方法里,就可以检查参数:

class Student(object):

    def get_score(self):
        return self._score

    def set_score(self,value):
        if not isinstance(value,int):
            raise ValueError('score must be an integer!')

        if value<0 or value>100:
            raise ValueError('score must between 0~100!')
        self._score=value

s=Student()
s.set_score(60)
print(s.get_score())   #60

s.set_score(9999)
print(s.get_score())  #    raise ValueError('score must between 0~100!')
ValueError: score must between 0~100!

还记得装饰器(decorator)可以给函数动态加上功能吗?对于类的方法,装饰器一样起作用。Python内置的@property装饰器就是负责把一个方法变成属性调用的:

class Student(object):

    @property
    def score(self):
        return self._score

    @score.setter
    def score(self,value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')

        if value < 0 or value > 100:
            raise ValueError('score must between 0~100!')
        self._score=value
s=Student()
s.score=60
print(s.score)   #60
s.score=7777
print(s.score)   #报错:

还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性:

class Student(object):

    @property
    def birth(self):
        return self._birth

    @birth.setter
    def birth(self,value):
        self._birth=value

    @property
    def age(self):
        return 2015-self._birth

ss=Student()
ss.birth=2013
print(ss.age)  #2
print(ss.birth)  #2013
ss.age=2  #报错:AttributeError: can't set attribute

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值