面向对象的成员与嵌套
成员:
一.变量
变量包括:实例变量(字段)和类变量(静态字段),在定义和使用中有区别,本质区别是内存中保存的位置不同.(实例变量保存在对象中,类变量保存在类中.)
class Provice: country = '中国' #类变量 def __init__(self, name): self.name = name #实例变量 # 访问实例变量,通过对象 obj = Provice('北京市') print(obj.name) #访问类变量,通过类 print(Provice.country) 结果: 北京市 中国
实例变量与类变量的内存位置:
类变量在内存中只保存一份
实例变量在每个对象中都保存一份
应用场景: 通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段.
二.方法
方法包括:普通方法,静态方法,类方法.三种方法在内存中都在类中,区别在于定义和调用方式不同.
普通方法: 由对象调用,至少有一个self参数,执行普通方法时,自动调用该方法的对象赋值给self.
静态方法: 由类调用,定义时在方法上面写@staticmethod,无默认参数.
类方法: 由类调用,定义时在方法上面写@classmethod,至少有一个cls参数,执行类方法时,自动调用该方法的类复制给cls.
class Foo: def func(self): #至少有一个self参数 print('普通方法') @classmethod def func1(cls): #至少有一个cls参数 print('类方法') @staticmethod def func2(): #可以没有参数 print('静态方法') obj = Foo() #实例化一个对象 obj.func() #通过对象调用普通方法 obj.func1() #可以通过对象调用类方法,一般不建议用 obj.func2() #可以通过对象调用静态方法,一般不建议用 Foo.func1() #通过类调用类方法 Foo.func2() #通过类调用静态方法 结果: 普通方法 类方法 静态方法 类方法 静态方法
相同点: 所有的方法,都属于类中,在内存中只保存一份.
不同点: 方法的定义不同,调用时自动传入的参数不同.
静态方法的使用: 如果方法无需使用对象中封装的值,就可以使用静态方法.
三.属性
属性是普通方法的变种
class Foo:
def func(self):
print('普通方法')
@property #定义属性时,方法上面加@property
def func1(self): #属性定义时,只有一个self参数,不能加参数
return '属性'
obj = Foo()
obj.func() #普通方法调用时,需要加括号
ret = obj.func1 #属性调用时,无需加括号
print(ret)
结果:
普通方法
属性
属性存在的意义是调用的时候不需要加括号.
属性的应用场景: 类中的方法,既不需要传参数且有返回结果.可以使用@property.
类的成员修饰符
每一个类的成员都有两种形式: 公有成员, 私有成员
公有成员: 在任何地方都能访问
私有成员:只有在类的内部可以访问
公有成员与私有成员的定义不同:私有成员命名时,前两个字符是下划线.(__init__等特殊成员除外)
class Foo: def __init__(self): self.name = '公有字段' self.__foo = '私有字段' def per(self): print(self.__foo) obj = Foo() print(obj.name) obj.per() print(obj.__foo) 结果: 公有字段 私有字段 报错
公有成员与私有成员的访问限制不同:
字段:
公有字段:对象可以访问,类内部可以访问,派生类也可以访问.
私有字段:只有类内部可以访问.
class Foo: def __init__(self): self.foo = '公有字段' def func(self): print(self.foo) #类内部访问 class Foo1(Foo): def show(self): print(self.foo) #派生类访问 obj = Foo() print(obj.foo) #通过对象访问 obj.func() #类内部访问 obj1 = Foo1() obj1.show() #派生类访问 结果: 公有字段 公有字段 公有字段
class Foo: def __init__(self): self.__foo = '私有字段' def func(self): print(self.__foo) #类内部访问 class Foo1(Foo): def show(self): print(self.__foo) #派生类访问 def per(self): self.func() obj = Foo() obj.func() #类内部访问==>正确 # print(obj.__foo) #通过对象访问==>错误 obj1 = Foo1() # obj1.show() #派生类访问==>错误 obj1.per() #派生类通过基类内部访问==>正确. #实质是通过类内部访问
静态字段:
公有静态字段:类可以访问,类内部可以访问,派生类可以访问
私有静态字段:只有类内部可以访问.
class Foo: name = '公有静态字段' def func(self): print(Foo.name) class Foo1(Foo): def show(self): print(Foo.name) print(Foo.name) #类访问 obj = Foo() obj.func() #类内部可以访问 obj1 = Foo1() obj1.show() #派生类中可以访问 结果: 公有静态字段 公有静态字段 公有静态字段
class Foo: __name = '私有静态字段' def func(self): print(Foo.__name) class Foo1(Foo): def show(self): print(Foo.__name) def per(self): self.func() print(Foo.__name) #类访问==>错误 obj = Foo() obj.func() #类内部访问==>正确 obj1 = Foo1() obj1.show() #派生类中访问==>错误 obj1.func() #派生类通过基类内部访问==>正确
方法,属性的成员修饰符与上述方式相似.私有成员只能在类内部使用.
注意:如果非要访问私有属性,可以通过对象._类__属性名
class Foo: __name = '私有静态字段' def func(self): print(Foo.__name) class Foo1(Foo): def show(self): print(Foo.__name) def per(self): self.func() obj = Foo() print(obj._Foo__name) 结果: 私有静态字段