面向对象高级特性
类属性与实例属性
类属性就是类对象所拥有的属性,它被所有类对象的实例对象所共有,在内存中只存在一个副本。
在前面的例子中我们接触到的就是实例属性(对象属性),它不被所有类对象的实例对象所共有,在内存中的副本个数取决于对象个数。
class People(object):
#属性名和对象没有绑定在一起,为类属性:
country='china'
#构造方法:创建对象时会自动执行的方法
def __init__(self,name,age):#传入name,age两个属性
#name,age是和self绑定在一起,所以是对象(实例)属性 self.xxxx--->这种情况大多是对象属性
self.name=name#将属性和对象绑定在一起
self.age=age
#实例化对象的过程:将类变成对象的过程为实例化过程
p1=People("粉条",10)
p2=People("粉丝",12)
#访问类属性:通过类名和对象名均可访问
#访问的规则:对象访问属性,先看有没有该对象属性。如果有,返回;如果没有,则查看是否有类属性:
print(People.country)
print(p1.country)
print(p2.country)
#访问对象属性:只能通过对象名访问
#print(People.name)
print(p1.name)
print(p2.age)
#修改类属性:如果直接修改为 对象名.属性名=xxxx,判断该对象是否有该属性。如果有,直接修改;如果没有,添加该属性信息
print("修改前:")
print(People.country)
print(p1.country)
print("正在修改:")
p1.country='uk'#只给p1添加了一个对象属性
print(People.country)
print(p1.country)
print(p2.country)#通过p2访问类属性依旧是原来的值
-------------------------------------------------------------------
china
china
china
粉条
12
修改前:
china
china
正在修改:
china
uk
china
类方法与静态方法
类方法是类对象所拥有的方法,需要用修饰器一般以@classmethod来标识其为类方法,
- 对于类方法,第一个参数必须是类对象,作为第一个参数
(cls是形参, 可以修改为其它变量名,但最好用’cls’了) - 能够通过实例对象和类对象去访问。
静态方法需要用修饰器一般以@staticmethod来标识其为静态方法,
- 静态方法不需要多定义参数。
- 能够通过实例对象和类对象去访问。
"""
类方法
实例方法
静方法
"""
from datetime import date
from datetime import time
from datetime import datetime
from datetime import timedelta
class Date(object):
def __init__(self, year=2019, month=6, day=20):
self.year = year
self.month = month
self.day = day
# 默认类的第一个参数是self,这种方法我们称为实例方法:
def show(self):
print("年:%s 月:%s 日:%s" % (self.year, self.month, self.day))
#类里面的函数被@classmethod装饰器装饰的函数,被称为类方法
#特点:python 解释器默认传递的第一个参数是类名,而不是对象self
#需要返回值是类(Date:year,month,day)时,而不是只需要其中一个属性进行修改时,需要用类方法
@classmethod
def as_str(cls, s): # s = '6/20/2019'
month, day, year = s.split('/') # ['6', '20', '2019']
d1 = cls(year, month, day)
return d1#返回的是一个对象
# print(Date)
# print(cls)
# d1.show()
#类里面的函数被装饰器@staticmethod装饰的函数 称为静态方法
#特点:python解释器默认不会传递任何参数给函数:
#静态方法的优点在于不需要传self 能够节约时间和内存空间
@staticmethod
def is_valid(s):#s='6/20/2019'
month,day,year=map(int,s.split('/'))
return year>0 and 0<month<=12 and 0<day<=31
#需求2:调用实例方法的代码
d = Date()
# 调用的是类的实例方法
d.show()
#需求3:调用类方法的代码
d1=Date.as_str('2/16/2019')
d1.show()
##需求1:用户传入字符串类型的日期,如何调用show方法呢?
#s='6/20/2019'
#month,day,year=s.split('/')#['6','20','2019']
#d1=Date(year,month,day)
#d1.show()
##需求4:用户传入字符串类型的日期,不显示,只判断该日期是否合法?year>0 0<month<12 0<day<31
#s='6/20/2019'
#month,day,year=map(int,s.split('/'))#['6','20','2019']-->[6,20,2019] ###注意map方法 可以字符串转整形
#print(year>0 and 0<month<=12 and 0<day<=31)
#调用静态方法的代码
result=Date.is_valid('30/20/2019')
print(result)
--------------------------------------------------------------
年:2019 月:6 日:20
年:2019 月:2 日:16
False
property类属性
"""
1).python内置的@property装饰器就是负责把一个方法变成属性调用的;
2)@property本身又创建了另一个装饰器@state.setter.负责把一个setter方法变成属性赋值,于是,我们就拥有一个可控的属性操作
3)@property广泛应用在类的定义中,可以让调用者写出简短的代码,同时保证对参数进行必要的检查,这样,程序运行时就减少了出错的可能性
"""
import time
from datetime import date
from datetime import time
class Date(object):
def __init__(self,year,month,day):
self.__year=year#私有属性
self.__month=month
self.__day=day
@property
def year(self):
return self.__year
@property
def month(self):
return self.__month
@property#获取属性信息的
def day(self):
return self.__day
@month.setter #属性赋值时会自动调用
def month(self,value): #在属性赋值时会自动调用
if 0<value<=12:
self.__month=value
else:
raise Exception("月份错误")
@month.deleter
def month(self): #属性删除时自动执行的内容:1,当del对象名,属性名
print("正在删除属性信息%s" % (self.__month))
# def __str__(self):
# return '%s-%s-%s' %(self.year, self.month, self.day)
##1.正常情况下外部是可以访问属性,也可以修改属性信息的
#d=Date(2019,6,25)
#print(d.year)#访问year属性
## print(str(d))
## print(d.__str__())
#d.year=2020#修改year属性
#print(d.year)
##2.可以访问属性,不可以任意修改属性
#d=Date(2019,6,25)
#print(d.year())
#print(d.month())
#print(d.day())
##3.可以访问属性,不可以任意修改属性,并保证属性访问的简洁性
#d=Date(2019,6,25)
#print(d.year)
#print(d.month)
#print(d.day)
#4..可以访问属性,也可以修改属性,但在修改属性时要判断其合法性
d=Date(2019,6,25)
print(d.month)
d.month=10
print(d.month)
del d.month
#del d.year
--------------------------------------------------------------
6
10
正在删除属性信息10