面向对象编程(二)
面向对象中的成员
属性就意味着一组数据,方法是意味着某种行为。
实例属性
创建对象就是实例化的过程,实例也就意味着对象,实例属性属于对象,只能通过对象访问
定义:self.属性名称
访问:self.属性名称 或 对象.属性名称
练习
定义一个省份类,打印输出班级每位同学所在的国家与省份。
class Province():
# 国家、省份都是数据,为属性
def __init__(self,country,name):
# 实例属性,self.属性名
self.country = country
self.name = name
# 在类中,尽量使代码进行模块化,单独封装打印方法
def print_info(self):
print(self.country, self.name) # 中国 河南 中国 北京 self就是对象本身,通过self去访问
# print(zs.country,zs.name) # 可以通过每个对象访问,但不建议使用
# print(Province.country, Province.name) # 会报错,提示Province没有country和name属性。因为country和name是每一个实例化对象的属性,一个类是可以创建多个对象的,通过类名.属性名访问的话,不知道你要访问的是哪个对象
# 实例化
zs = Province('中国', '河南')
zs.print_info()
lisi = Province('中国', '北京')
lisi.print_info()
一个类是可以创建多个对象的,通过类名.属性名访问的话,不知道你要访问的是哪个对象,所以不能通过类名.属性名进行访问。
在上述例子中,重复传入了参数‘中国’,而且每次传入的都一样,可以在实例化属性的时候把 国家写为中国
class Province():
def __init__(self,name):
self.country = '中国'
self.name = name
实例化传参的时候,只需要传递name就可以了。每创建一个对象就会创建一个 self.country = ‘中国’ 的实例属性,会造成内存的浪费,可以通过类属性解决。
类属性(静态属性)
类属性属于类,保存在类中。在创建时,仅创建一份,并且所有对象都共享静态属性。执行时可以是类访问也可以是对象访问。
定义:直接在类中定义,所有方法的外面
访问:类名.属性名称 或 self.属性名称 或 对象.属性名称
class Province():
country = '中国' # 类属性(静态属性)
def __init__(self,name):
self.name = name
def print_info(self):
# print(self.country, self.name) # 中国 河南 中国 北京 self就是对象本身,通过self去访问 类属性
# print(zs.country,zs.name) # 可以通过每个对象访问,但不建议使用
print(Province.country) # 类属性,是可以通过类名.属性名 来访问的
# 实例化
zs = Province('河南')
zs.print_info()
lisi = Province('北京')
lisi.print_info()
属性总结
在实际开发中,如果属性的值是固定的,不随对象的改变而改变。那就使用静态属性(类属性),这样有利于节省内存的消耗。而如果属性的值随对象的改变而改变,就使用实例属性(如上述代码中的name)。
实例方法
普通方法保存在类中,在实例化对象后,一般通过对象调用。第一个参数必须为系统自建参数,默认为 self,代指对象本身。
class Test_one:
def __init__(self):
self.name = 'zhangsan'
# 实例方法,通常用于需要访问实例属性
# self为系统自建的参数,再有其他参数,在后面直接加上就可以了
def test_one(self): # 为了方便访问实例属性的
print(self.name)
T = Test_one()
T.test_one() # zhangsan
注意:
1.当需要在方法中使用实例属性时,通常使用实例方法
2.self 仅仅是变量名,但最好不要修改
类方法
类方法通过在方法上面添加 @classmethod 装饰器,使得方法变为类方法,保存在类中。
class Test_one:
def __init__(self):
self.name = 'zhangsan'
def test_one(self):
print(self) # 对象本身 <__main__.Test_one object at 0x000001798A1E7710>
print(self.name)
@classmethod
def cls_md(cls, age): # 补齐时,自建参数不在是self,而是cls,代指当前类
print(cls) # 类的本身 <class '__main__.Test_one'>
print(age) # 30
T = Test_one()
T.test_one()
T.cls_md('30')
注意:
1.类方法不需要传入self。但有一个系统自建参数为cls,cls代指类本身;
2.类方法一般通过类调用,也可通过对象调用
静态方法
静态属性为类属性,静态方法并非类方法。
静态方法通过在方法上面添加 @staticmethod 装饰器定义,保存在类中
class Test_one:
def __init__(self):
self.name = 'zhangsan'
def test_one(self):
print(self) # 对象本身 <__main__.Test_one object at 0x000001798A1E7710>
print(self.name)
@classmethod
def cls_md(cls, age): # 补齐时,自建参数不在是self,而是cls,代指当前类
print(cls) # 类的本身 <class '__main__.Test_one'>
print(age) # 30
@staticmethod
def stat_md(): # 括号内并没有自动添加内容,不能访问实例方法
print('我是静态方法') # 我是静态方法
T = Test_one()
T.test_one()
T.cls_md('30')
T.stat_md()
注意:
1.静态方法不需要传入self参数,即使传入了self参数也并不像普通方法那样代指对象本身,仅仅是一个普通的形参。
2.静态方法的调用虽然可以通过对象调用,但一般由类调用。
3.静态方法的参数并不代表对象这一特点,使静态方法在类中使用起来更像一个单纯的函数。完全可以将静态方法放在类的外部,当成函数使用。但是放在类中,便于使用与维护。
import time
class TimeTest:
def show_time(self): # 在show_time里并没有调用self对象
# print(time.localtime()) # 以元组的形式,返回当前的时间,
# 进行时间格式化
print(time.strftime('%H:%M:%S', time.localtime()))
T = TimeTest()
T.show_time() # 方法跟类里的实例没有关系
可以改为静态方法,在类中就为了便于管理,跟写在类内外没有关系,放到外面就可以直接用
import time
class TimeTest:
@staticmethod
def show_time(): # 实例方法要传入self方法,但是在函数中未用到实例对象,可以省略,改为静态方法
print(time.strftime('%H:%M:%S', time.localtime()))
T = TimeTest()
T.show_time()
只要普通字段(实例属性)保存在对象当中,就不能通过类名来访问,其他的属性和方法都是保存在类当中的。