Python入门之(7.2)类和对象

目录

类和对象

1.1类的定义和对象的创建

1.2实例变量及封装

1.3方法

1.4属性方法

1.5类中的其他内置方法和属性


类和对象

在Python中,一切皆为对象。例如,所有字符串是str类的实例,所有列表是list类的实例等。尽管每个字符串的实际内容不同,但是他们的操作方法都是相同的,如取子串、定位、切片等。前面所学的str、int、float、list、turple、dictionary和set数据类型都是Python定义的内建类。这些类型的变量都是该数据类型的一个实例,即对象。

类由属性和方法组成,属性是描述对象特征的集合,方法是对象的行为。

1.1类的定义和对象的创建

Python中定义类的语法格式如下:

class 类名:
    [类变量]
    [def __init__(self,paramers):]
    [def 函数名(self,…)]

注意:

  1. 直接定义在类体中的变量叫做类变量,是所有对象共享的变量,也称静态变量静态数据,与所属的类对象绑定,不依赖于实例对象
  2. 在类的方法中定义的变量叫做实例变量。类的方法的定义和普通函数的定义类似,但方法必须以self作为第一个参数。方法调用时,可以不传递self参数;
  3. 当创建对象时,self参数指向该对象。这样,当方法调用时,会通过self参数得知哪个对象调用了该方法;
  4. 实例方法必须绑定到一个实例对象上才能被调用;
  5. 当一个类定义完之后,就产生了一个类对象(与类名相同);
  6. 实例对象通过类名后跟圆括号来实例化;
  7. 在Python中,对象支持两种操作:引用和实例化。引用是通过类对象来调用类中的属性或方法;实例化是生成类对象的实例,也称实例对象,通过实例对象来引用类中的属性或方法。

简单的类定义,类的示例代码如下:

class fruit:     #通过关键字class定义一个类
    name='apple'
    price=6.7
    #定义一个实例方法,方法至少有一个参数self
    def printName(self):
        print(self.name)
        print(self.price)
if __name__=='__main__':
    print('通过类对象调用类变量:')
    #通过类对象名.变量名来访问类变量
    print('fruit.name={},fruit.price={}'.format(fruit.name,fruit.price))
    print('通过实例对象调用方法和类变量:')
    myFruit=fruit()     #通过类名()的方式来初始化一个实例对象
    myFruit.printName()   #通过实例对象名.方法名来访问实例方法
    #通过实例对象名.变量名来访问类变量
    print('myFruit.name={},myFruit.price={}'.format(myFruit.name,myFruit.price))
    print('修改类变量的值')
    myFruit.name='pear'     #可以在类外修改类变量的值
    myFruit.price=3.5
    print('myFruit.name={},myFruit.price={}'.format(myFruit.name, myFruit.price))
    #不能通过类对象名.方法名来访问实例方法,下面的语句是错误的
    #fruit.printName()

运行结果为:

E:\PycharmProjects\PythonTest\venv\Scripts\python.exe E:/PycharmProjects/PythonTest/ssss.py
通过类对象调用类变量:
fruit.name=apple,fruit.price=6.7
通过实例对象调用方法和类变量:
apple
6.7
myFruit.name=apple,myFruit.price=6.7
修改类变量的值
myFruit.name=pear,myFruit.price=3.5

Process finished with exit code 0

 

1.2实例变量及封装

实例化之后,每个实例单独拥有的变量叫做实例变量。实例变量是与某个类的实例相关联的数据值,这些值独立于其他实例或类。当一个实例被释放后,这些变量同时被释放。

在Python中,实例变量的定义如下:       self.变量

只要以self定义的变量都是实例变量。该变量可以定义在任何实例方法内。

实例变量的初始化最好通过定义__init__()或__new__()构造方法来完成。该方法在定义对象的时候自动调用。如果同时定义了这两种方法,优先调用__new__()方法来完成实例化。

调用实例变量有如下两种方式:

  1. 在类外通过变量直接调用;
  2. 在类内通过self间接调用。

Python中的封装,其实是使用构造方法将内容封装到对象中,然后通过对象直接或者通过self间接获取被封装的内容。

与其他语言不同的是,Python没有提供private、public这样的访问控制符,因此上述方式定义的实例变量在类外可以使用。

如果要实现真正的封装,让实例变量或方法成为私有的,需要在变量名和方法名前加双下划线,如__valueName或__functionName。

实例变量应用的代码如下:

class point1:   #定义类point1
    def __init__(self,x,y):    #定义类point1的构造方法,创建对象时自动调用
        self.x=x               #创建实例变量x,并初始化
        self.y=y               #创建实例变量y,并初始化
    def move(self,x,y):        #定义实例方法,完成点的移动
        self.x = x             #类内通过self间接引用实例变量
        self.y = y
    def setX(self,x):          #定义实例方法,设置x
        self.x=x
    def setY(self,y):          #定义实例方法,设置y
        self.y=y
    def getX(self):            #定义实例方法,获得x的值
        return self.x
    def getY(self):            #定义实例方法,获得y的值
        return self.y
    def print(self):           #定义实例方法,输出x和y
        print('[',self.x,',',self.y,']')
#定义类point2,实例变量为私有
class point2:
    def __init__(self,x,y):    #定义类point2的构造方法,创建对象时自动调用
        self.__x=x               #创建私有实例变量__x,并初始化
        self.__y=y               #创建私有实例变量__y,并初始化
    def move(self,x,y):        #定义实例方法,完成点的移动
        self.__x = x             #类内通过self间接引用实例变量
        self.__y = y
    def setX(self,x):          #定义实例方法,设置__x
        self.__x=x
    def setY(self,y):          #定义实例方法,设置__y
        self.__y=y
    def getX(self):            #定义实例方法,获得__x的值
        return self.__x
    def getY(self):            #定义实例方法,获得__y的值
        return self.__y
    def print(self):           #定义实例方法,输出__x和__y
        print('[',self.__x,',',self.__y,']')
        #print('hello',self.name)
#定义类hello
class hello:
    def setName(self,yourName):    #定义实例方法
        self.name=yourName         #name是实例变量
    def print(self):               #定义实例方法,使用了实例变量
        print('hello',self.name)
if __name__=='__main__':
    print('point1实例变量使用演示:')
    p=point1(0,0)   #自动调用构造方法__init()完成实例对象的创建
    p.print()      #调用实例方法,self参数不需要明确传递
    p.move(4,5)
    p.print()
    p.x=10       #类外可以直接使用实例变量,格式为实例对象名.实例变量名
    p.y=20
    p.print()
    p.setX(3.5)
    p.setY(4.5)
    print('p.x={},p.y={}'.format(p.x,p.y))
    print('point2实例变量使用演示:')
    q=point2(0,0)     #初始化实例对象q
    q.print()
    q.move(4,5)
    q.print()
    #下面的语句不会报错,但是私有变量x和y不会被重新赋值
    q.__x=10
    q.__y=20
    q.print()
    q.setX(3.5)
    q.setY(4.5)
    print('q.x={},q.y={}'.format(q.getX(),q.getY()))
    print('hello类的演示:')
    h=hello()
    h.setName('Mary')
    h.print()

运行结果为:

E:\PycharmProjects\PythonTest\venv\Scripts\python.exe E:/PycharmProjects/PythonTest/ssss.py
point1实例变量使用演示:
[ 0 , 0 ]
[ 4 , 5 ]
[ 10 , 20 ]
p.x=3.5,p.y=4.5
point2实例变量使用演示:
[ 0 , 0 ]
[ 4 , 5 ]
[ 4 , 5 ]
q.x=3.5,q.y=4.5
hello类的演示:
hello Mary

Process finished with exit code 0

关于类变量和实例变量的使用,还需要注意以下两点:

  1. 在类方法中引用的变量必定是类变量。而在实例方法中,当引用的变量名与类变量名相同时,实例变量会屏蔽类变量,即引用的是实例变量;若实例对象没有该名称的实例变量,引用的是类变量;
  2. 如果在实例方法中更改某个实例变量,并且存在同名的类变量,则修改的是实例变量;若实例对象没有与类变量同名的实例变量,会创建一个同名称的实例变量。此时若要修改类变量,只能在类方法中修改。

1.3方法

在Python类中定义的方法通常有三种:实例方法、类方法以及静态方法。以下是这三种方法的定义和调用方式。

1.实例方法

实例方法一般都以self作为第一个参数,必须和具体的对象实例绑定才能访问,即必须由对象调用。执行时,自动将调用该方法的对象赋值给self。

2.类方法

类方法必须以cls作为第一个参数。cls表示类本身,定义时使用@classmethod装饰器。可以通过类名或实例对象名来调用。执行类方法时,自动将调用该方法的类赋值给cls参数。

3.静态方法

静态方法不需要默认的任何参数,跟一般的普通方法类似,但是方法内不能使用任何实例变量,定义时使用@staticmethod装饰器。静态方法可以通过类名或实例对象名来调用。

方法的定义与应用的示例代码如下:

class foo:
    animal='兔子'
    def __init__(self,feature):
        self.feature=feature

    def print(self):  #定义普通方法,至少有一个self参数
        print('调用了普通方法:')
        print('{}的特征是{}'.format(self.animal,self.feature))   #输出类变量和实例变量

    @classmethod          #类方法装饰器声明
    def enemy(cls,name):   #定义类方法,至少有一个cls参数,不能使用实例变量
        print('调用了类方法')
        enemyName=name    #enemyName为类方法内的变量,类外不可用
        #通过cls.类变量名的方法访问类变量(静态变量)
        print('{}的天敌是{}'.format(cls.animal,enemyName))

    @staticmethod         #静态方法装饰器声明
    def eat(name):        #定义静态方法,无默认参数,不能使用实例变量
        print('调用了静态方法')
        eatname=name       #eatname为静态方法中的变量,类外不可用
        #通过类名.类变量的方法访问类变量(静态变量)
        print('{}的食物是{}'.format(foo.animal,eatname))

if __name__=='__main__':
    t=foo(['长耳朵','三瓣嘴','两颗大门牙','毛柔软','红眼睛'])   #初始化实例对象
    t.print()   #利用实例对象调用普通方法
    t.enemy(['狼','老鼠'])                     #通过实例对象调用类方法
    foo.enemy(['黄鼠狼','狐狸'])                 #通过类名调用类方法
    t.eat(['青草','胡萝卜','白菜','薯类'])    #通过实例对象调用静态方法
    foo.eat(['苹果','南瓜'])                   #通过类名调用静态方法

运行结果为:

E:\PycharmProjects\PythonTest\venv\Scripts\python.exe E:/PycharmProjects/PythonTest/ssss.py
调用了普通方法:
兔子的特征是['长耳朵', '三瓣嘴', '两颗大门牙', '毛柔软', '红眼睛']
调用了类方法
兔子的天敌是['狼', '老鼠']
调用了类方法
兔子的天敌是['黄鼠狼', '狐狸']
调用了静态方法
兔子的食物是['青草', '胡萝卜', '白菜', '薯类']
调用了静态方法
兔子的食物是['苹果', '南瓜']

Process finished with exit code 0

 

1.4属性方法

python中的属性方法是普通方法的变种,即把一个方法变成静态属性。这样,方法在调用时就不用加小括号了。

属性方法定义有两种方式:

  1. 装饰器方式:定义方法时,使用@property装饰器;
  2. 静态属性方式:在类中定义值为property对象的静态属性。

属性方法格式为:   property(方法名1,方法名2,方法名3,‘描述信息’)

参数说明:

  1. 方法名1:调用对象.属性自动触发执行方法;
  2. 方法名2:调用对象.属性=XXX时,自动触发执行方法;
  3. 方法名3:调用del 对象.属性时,自动触发执行方法;
  4. 描述信息:是一个字符串,调用对象.属性.__doc__。此参数是该属性的描述信息。

实际上,property()方法中的3个方法参数可以分别对应获取属性的方法、设置属性的方法和删除属性的方法。这样,外部对象就可以通过类似于访问变量的方式来达到获取、设置或删除类内属性的目的。

属性方法应用的示例代码如下:

class book:  #定义book类
    def __init__(self,bookname,author,price):    #定义book类的构造方法
        #分别初始化3个实例变量
        self.__name=bookname
        self.__author=author
        self.__price=price
    def getname(self):    #定义普通实例方法
        return self.__name
    @property
    def getauthor(self):    #定义属性方法
        return self.__author
    def getprice(self):    #定义普通实例方法
        return self.__price
    #定义静态属性,当执行对象名.PRICE时,触发getprice()方法的执行
    PRICE=property(getprice)
    def print(self):    #定义普通实例方法
        print('书名:{},作者:{},价格:{}'.format(self.__name,self.__author,self.__price))

class goods:    #定义类goods
    #定义类goods的构造函数,并初始化3个实例变量
    def __init__(self,goodsname,produce,price):
        self.__name=goodsname
        self.__produce=produce
        self.__price=price
    def getname(self):  #定义普通实例方法
        return self.__name
    def changename(self,name):  #定义除self外,还有一个参数的方法
        self.__name=name
    def delname(self):    #定义一个实例方法,删除一个实例变量
        del self.__name
    #定义静态属性
    NAME=property(getname,changename,delname,'商品名称')
    def print(self):    #定义一个普通实例方法
        print('商品名:{},生产厂家:{},价格:{}'.format(self.__name,self.__produce,self.__price))
if __name__=='__main__':
    print('book类的演示:')
    bk=book('python程序设计','张三',45)   #初始化一个book类的实例对象bk
    print(bk.getname())  #普通实例方法调用
    print(bk.getauthor)   #装饰器属性方法调用
    print(bk.PRICE)       #静态属性方法调用
    bk.print()
    print('goods类的演示:')
    gds=goods('牛奶','三元',1.5)   #初始化goods实例对象gds
    print(gds.NAME)      #自动调用第一个参数中定义的方法:getname()
    gds.NAME='早餐奶'   #自动调用第二个参数中定义的方法:changename()
    del gds.NAME        #自动调用第三个参数中定义的方法:delname()
    #因删除了实例变量name,因此下面的调用会出错
    #gds.print()

运行结果为:

E:\PycharmProjects\PythonTest\venv\Scripts\python.exe E:/PycharmProjects/PythonTest/ssss.py
book类的演示:
python程序设计
张三
45
书名:python程序设计,作者:张三,价格:45
goods类的演示:
牛奶

Process finished with exit code 0

 

1.5类中的其他内置方法和属性

python类中还提供一些内置方法来完成特定的功能,如下表所示:

python内置方法
方法名或属性名功能描述
__init__(self,…)构造方法。初始化对象,在创建新对象时调用
__del__(self)析构方法。释放对象,在对象被删除之前调用
__new__(cls,*args,**kwd)初始化实例
__str__(self)在使用print语句时被调用
__getitem__(self,key)获取序列的索引key对应的值,等价于seq[key]
__len__(self)在调用内联函数len()时被调用
__cmp__(src,dst)比较两个对象src和dst

__getattr__(s,name)

获取属性的值
__setattr__(s,name,value)设置属性的值
__delattr__(s,name)删除name属性
__getattribute__()与__getattr__()类似
__call__(self,*args)对象后面加括号时触发执行,把实例对象作为函数调用
__iter__用于迭代器
__gt__(self,other)判断self对象是否大于other对象
__lt__(self,other)判断self对象是否小于other对象
__ge__(self,other)判断self对象是否大于或等于other对象
__le__(self,other)判断self对象是否小于或等于other对象
__eq__(self,other)判断self对象是否等于other对象
__doc__表示类的描述信息
__module__表示当前操作的对象在哪个模块
__class__表示当前操作的对象的类是什么
__dict__类或对象中的所有成员

内置方法应用的实例程序如下:

class fruit:
    def __init__(self,name,price):
        self.name=name
        self.price=price
    #此方法一般无须定义。析构函数的调用是由解释器在进行垃圾回收时自动触发执行的
    def __del__(self):
        pass
    def __call__(self, *args, **kwargs):    #对象()或者类()触发执行call()方法
        print('fruit {} is tasteful.'.format(self.name))
    def __str__(self):
        return 'the price of '+self.name+' is '+str(self.price)
    def __getattribute__(self, name):    #获取属性的方法
        return object.__getattribute__(self,name)
    def __setattr__(self, name, value):    #设置属性的方法
        self.__dict__[name]=value
if __name__=='__main__':
    print('fruit.__doc__:{}'.format(fruit.__doc__))
    obj=fruit('apple',5.5)
    print('obj.__module__:{0}'.format(obj.__module__))     #输出模块
    print('obj.__class__:{0}'.format(obj.__class__))  # 输出类
    print('obj.__dict__:{0}'.format(obj.__dict__))  # 输出类的成员
    obj()  #执行call()方法
    print(obj)  #如果定义了__str__()方法,则调用它
    obj.__dict__['_fruit__price']=6.5         #设置price属性
    print(obj.__dict__.get('_fruit__price'))

运行结果为:

E:\PycharmProjects\PythonTest\venv\Scripts\python.exe E:/PycharmProjects/PythonTest/ssss.py
fruit.__doc__:None
obj.__module__:__main__
obj.__class__:<class '__main__.fruit'>
obj.__dict__:{'name': 'apple', 'price': 5.5}
fruit apple is tasteful.
the price of apple is 5.5
6.5

Process finished with exit code 0

1.第12行和第24行有些不太明白,感觉第12行的函数像递归调用,第24行中把_fruit__price改成price之后运行结果是一样的

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值