No.20类成员&修饰符
No.20
今日概要
- 类成员
- 成员修饰符
内容回顾和补充
三大特性
-
封装
-
函数封装到类
-
数据封装到对象
class Foo: def __init__(self, name, age) self.name = name self.age = age obj = Foo('alex', 18)
-
-
继承
-
多态
内容详细
1.成员
- 类
- 类变量
- 绑定方法
- 类方法
- 静态方法
- 属性
- 实例(对象)
- 实例变量
1.1实例变量
class Foo:
def __init__(self,name):
self.name = name
def info(self):
pass
obj1 = Foo('alex')
obj2 = Foo('eric')

1.2类变量
class Foo:
city = '北京'
def __init__(self, name):
self.name = name
def func(self):
pass
obj1 = Foo('李杰')
obj2 = Foo('女神')
print(obj1.name)
print(obj2.name)
# Python中对象可以取类的变量,其它语言是谁的变量就谁去取。
print(Foo.city) # 其它语言只能这么取
print(obj1.city) # python可以对象取(这么写不太规范)
print(obj2.city) # python可以对象取

-
定义:写在类的下一级,和方法同一级。
-
访问:
类.类变量名称 对象.类变量名称 # Python中可以 -
面试题
class Base: x = 1 obj = Base() print(obj.x) # 先在对象中找,没有再去类中找。 obj.y = 123 # 在对象中添加了一个y=123的变量。 obj.x = 123 # 在对象中添加了一个y=123的变量,不能赋值类中的变量。 Base.x = 666 # 在类中修改了变量的值。class Base: x = 1 class Foo(Base): pass print(Base.x) print(Foo.x) Base.x = 666 print(Base.x) print(Foo.x) Foo.x = 999 print(Base.x) print(Foo.x)class Parent: x = 1 class Child1(Parent): pass class Child2(Parent): pass print(Parent.x, Child1.x, Child2.x) Child1.x = 2 print(Parent.x, Child1.x, Child2.x) Child2.x = 3 print(Parent.x, Child1.x, Child2.x)# 类不能找对象的变量 class Parent: x = 1 class Child(Parent): pass obj = Child() print(obj.x) obj.x = 2 # Child类的obj对象中创造一个变量 print(Child.x) # Child类中没有变量依旧去父类找![]()
总结:找变量时优先找自己,自己没有找类 或 基类;修改或赋值只能在自己的内部设置。
1.3绑定方法(普通方法)
- 定义:至少有一个self参数。
- 执行:先创建对象,由对象.方法调用。
class Foo:
def func(self,a,b):
print(a,b)
obj = Foo()
obj.func(1,2)
# 建议按下面格式写,不会浪费对象空间。
class Foo:
def __init__(self):
self.name = 666
def func(self, a, b):
print(self.name, a, b)
1.4静态方法
- 定义:
- @staticmethod 装饰器
- 参数无限制
- 执行:
- 类.静态方法名()
- 对象.静态方法名()(不推荐)
# 不需要通过类创建对象封装数据来使用的方法
class Foo:
def __init__(self):
self.name = 666
def func(self, a, b): # 绑定方法 会用到对象中封装的数据
print(self.name,a, b)
@staticmethod # 静态方法 可以不用传参数
def f1():
print(123)
obj = Foo()
obj.func(1, 2)
Foo.f1() # 通过类执行静态方法,可以不用创建对象。
obj.f1() # Python中对象也可以调用静态方法,但是不推荐。
1.5类方法
-
定义:
- @classmethod 装饰器
- 至少有cls参数,当前类
-
执行:
- 类.类方法()
- 对象.类方法()(不推荐)
class Foo:
def __init__(self):
self.name = 666
def func(self, a, b): # 绑定方法
print(self.name,a, b)
@staticmethod # 静态方法 可以不用传参数
def f1():
print(888)
@classmethod # 类方法 其它语言没有类方法 本质上和静态方法一样 无非给静态方法多传一个参数
def f2(cls,a,b):
print('cls是当前类',cls)
print(a,b)
obj = Foo()
Foo.f2(1,2)
obj.f2(1,2) # 类方法也可以通过对象调用
面试题:
# 请问 @classmethod 和 @staticmethod 的区别?
一个是类方法,一个是静态方法
定义:
类方法:用@classmethod作装饰器,且至少有一个cls参数。
静态方法:用@staticmethod作装饰器,且参数无限制。
调用:
类.方法直接调用。
对象.方法也可以调用。
1.6属性
- 定义:
- @property 装饰器
- 只有一个self参数
- 执行:
- 对象.方法(不用加括号)
class Foo:
def f1(self, a, b):
# 绑定方法
print(a, b)
@staticmethod
def f2(): '''传不传参数都无所谓'''
# 静态方法(参数无要求)
print(888)
@classmethod '''其它语言没有类方法 本质上和静态方法一样 无非给静态方法多传一个参数'''
def f3(cls):
# 类方法(至少有一个cls参数)
print('cls是当前类',cls)
@property '''变成属性被调用时不用加括号'''
def f4(self):
# 属性(只能有self参数)
print(888)
class Foo:
@property # 变成属性被调用时不用加括号 不能有其它参数
def func(self):
print(123)
return 666
obj = Foo()
result = obj.func # 不用加括号
print(result)
# 属性的应用
class Page:
def __init__(self, total_count, current_page, per_page_count=10):
self.total_count = total_count # 数据总个数
self.current_page = current_page # 查看页码
self.per_page_count = per_page_count # 每页数据个数
@property
def start_index(self):
return (self.current_page - 1) * self.per_page_count
@property
def end_index(self):
return self.current_page * self.per_page_count
USER_LIST = []
for i in range(321):
USER_LIST.append('alex-%s' %(i,))
# 请实现分页展示:
current_page = int(input('请输入要查看的页码:'))
p = Page(321, current_page)
data_list = USER_LIST[p.start_index:p.end_index]
for item in data_list:
print(item)
2.成员修饰符
- 公有:所有地方都能访问
- 私有:只有自己可以访问
# 实例变量
class Foo:
def __init__(self, name):
#self.name = name # 公共实例变量
self.__name = name
def func(self):
print(self.__name)
obj = Foo('alex')
print(obj.__name) # 外部无法访问
obj.func() # 内部可以访问
# 类变量
class Foo:
__x = 1
@staticmethod
def fun():
print(Foo.__x)
print(Foo.__x) # 外部无法访问
Foo.fun() # 内部可以访问
# 方法
class Foo:
def __fun(self):
print('msg')
def show(self):
self.__fun()
obj = Foo()
obj.__fun() # 外部无法访问
obj.show() # 内部可以访问
# 继承
class Base:
def __f1(self):
print('Base.f1')
class Foo(Base):
def fun(self):
self.__f1() # 对于父类而言子类的内部依旧还是外部
obj = Foo()
obj.__f1 # 外部无法访问
obj.fun() # 子类内部无法访问
Foo虽然是Base的子类,但是Foo内部依然无法访问Base的私有方法。
3.补充
class Foo:
def __init__(self, num):
self.num = num
lst = []
for i in range(10):
lst.append(Foo)
for i in range(len(lst)):
obj = lst[i](i)
print(obj.num)
class Foo:
def __init__(self, name):
self.__x = name
B = Foo
obj = B('alex')
class Foo:
def f1(self):
print('f1')
def f2(self):
print('f2')
obj = Foo()
v = [obj.f1, obj.f2]
for item in v:
item()
class Foo:
def f1(self):
print('f1')
def f2(self):
print('f2')
def f3(self):
v = [self.f1, self.f2]
for item in v:
item()
obj = Foo()
obj = f3()
class Account:
def login(self):
pass
def register(self):
pass
def run(self):
info = {'1':self.register, '2':self.login}
choice = input('请选择')
method = info.get(choice)
method()
# 在Python3中这两种写法一样,因为所有的类都会默认继承object类,全部都是新式类。
class Foo:
pass
class Foo(object):
pass
认为object类是帮忙开辟内存的,Foo()会立即执行__init__方法,Foo类中没有此方法,系统也不报错因为object中有。
# 如果在Python2中这样定义,称其为经典类。
class Foo:
pass
# 如果在Python2中这样定义,称其为新式类。
class Foo(object):
pass
赠送
# 强制访问私有成员
class Foo:
def __init__(self, name):
self.__x = name
obj = Foo('alex')
print(obj._Foo__x) # 强制访问私有实例变量
总结
-
数据封装
-
继承关系的查找
-
嵌套(组合)
class School(object): def __init__(self, title, addr): self.title = title self.address = addr class ClassRoom(object): def __init__(self, name, school_obj): self.name = name self.school = school_obj s1 = School('北京', '沙河') s2 = School('上海', '浦东') s3 = School('深圳', '南山') c1 = ClassRoom('人工智能', s1) c1.name c1.school.title c1.school.address # 分割 v = [11,22,33,{'name':'上海', 'addr':'浦东'}] v[0] v[3]['name']


浙公网安备 33010602011771号