【python】学习面向对象编程(二)

注意点

  • 对象的__dict__是可以赋值修改的,但类的__dict__不能修改,是只读的
    对象和类的__dict__有各自的存储空间

  • 类的属性可以被各个对象共享

上一节的补充点:

  • 可以通过__slots__限定对象可添加的属性
class Person:
  __slots__=['age']
  pass

p=Person()
p.age=1 #可以
p.num=2 #报错

方法相关的知识点

方法的概念和作用

  • 封装一系列的行为和动作
  • 和函数很类似,但是有所区别:调用方式
  • 调用方式:p.eat()
    要调用对象

方法的划分

  • 方法的第一个参数必须是要接收的数据类型
  • 实例方法:需要传入实例;self
  • 类方法:需要传入类;cls
  • 静态方法:没有限制
class Person:
  def eat2(self):
    print('this is实例方法')

  @classmethod
  def leifangfa(cls):
    print('this is类方法')

  @staticmethod
  def jingtaifangfa():
    print('this is 静态方法')
#调用:
p=Person()
p.eat2()
Person.leifangfa()
Person.jingtaifangfa()

方法的存储

  • 方法都存储类的__dict__里面,不存储在对象里面

实例方法

class Person:
  def eat(self,food): 
  print('eating',food)

p=Peason()
p.eat('potato')
  • 标准调用:利用实例(即对象)去调用,不需要自己传递第一个参数self
  • 其他调用(基本不用):1使用类调用2间接调用

类方法

class Person:
  @classmethod
  def leifangfa(cls,a):
    print('这是一个类方法',cls,a)

Person.leifangfa(123)
#这是一个类方法  123

p=Person()
p.leifangfa(666)
#这是一个类方法  666
#这告诉我们:可以用实例调用类方法,但是实例会被忽略

func=Person.leifangfa
func(111)
#这是一个类方法  111
#装饰器的作用:保证这个函数原本不改变的情况下,给这个函数增加一些功能

class A(Person):
  pass
A.leifangfa(0)
#这是一个类方法  0

静态方法

class Person:
  @staticmethod
  def jingtai():
    print('这是一个静态方法')

Person.jingtai()
#这是一个静态方法
p=Person()
p.jingtai()
#这是一个静态方法
func=Person.jingtai
func()
#这是一个静态方法

  • 可以通过类调用,也可以用实例调用

补充内容

1、访问权限问题

  • 在实例方法里面可以找到类属性、实例属性
  • 在类方法里面只可以找到类属性,不能找到实例属性
  • 在静态方法里面不能找到类属性也不能找到实例属性
    但是可以通过索引类去获取
  • cls表示默认传入的是类,self表示默认传入实例

2、类的补充内容

元类

  • 创建类对象的类
  • 元类可以创建新的类
  • 对象10的类是int,int的类是type
    对象"abc"的类是str,str的类是type
    type就是元类

用元类创建类对象

#type(类名,tuple,dict)
def run:
  print("run")
xxx=type("Dog",(),{"count":0,"run":run})
# 得到一个叫xxx的类
# 它有类属性count=0,类方法run
p=xxx()
p.run()
#run
print(p.count) #0

类的描述

  • 类本身的功能、类属性、类方法等
  • 写在前面用"""引起来

类的描述的获取

  • 1.用help(Person)获得所有的描述
  • 2.使用内置模块pydoc

类的属性分类

  • 保证数据安全性
  • 通过下划线完成伪私有效果
  • 公有属性
    _保护属性
    __私有属性

1.公有属性

class Animal:
  x=10
  def test(self):
    print(Animal.x)
    print(self.x)
  pass

class Dog(Animal):
  def test2(self):
    print(Dog.x)
    print(self.x)
  pass

#测试代码
a=Animal()
a.test()
#可以得到10,即在类的内部可以访问到这个公有属性
d=Dog()
d.test2()
#可以得到10,即在类的外部可以访问到这个公有属性

print(Animal.x)
print(Dog.x)
print(a.x)
print(d.x)
#这样也都可以访问到x
  • 跨模块访问公有属性
# file1.py
a=666
# file2.py
import file1
print(file1.a) #666
# file3.py
from file1 import *
print(a) #666

以上3段代码告诉我们:可以直接访问到a

2.受保护的属性

class Animal:
  _x=10
  def test(self):
    print(Animal._x)
    print(self._x)
  pass

class Dog(Animal):
  def test2(self):
    print(Dog._x)
    print(self._x)
  pass

#测试代码
a=Animal()
a.test()
#可以得到10,即在类的内部可以访问到这个受保护的属性

d=Dog()
d.test2()
#可以得到10,即在类的外部可以访问到这个受保护的属性

print(Animal._x)
print(Dog._x)
print(a._x)
print(d._x)
#这样也都可以访问到x,但是会有警报(黄色波浪线)
  • 可以访问,但是会有警报,建议不要访问

  • what about跨模块访问受保护的属性?

# file1.py
_a=666
# file2.py
import file1
print(file1._a) #666
#可以访问但是有警报
# file3.py
from file1 import *
print(_a) 
# 无法访问 直接报错
  • 只可以用import的形式访问,不可以from...import...
  • 但是如果file1里加入以下代码的话就可以正常访问这个受保护的属性
__all__=['_a']

3.私有属性

class Animal:
  __x=10
  def test(self):
    print(Animal.__x)
    print(self.__x)
  pass

class Dog(Animal):
  def test2(self):
    print(Dog.__x)
    print(self.__x)
  pass

#测试代码
a=Animal()
a.test()
#可以得到10,即在类的内部可以访问到这个私有属性

d=Dog()
d.test2()
#报错,不可以得到10,即在类的外部不可以访问到这个私有属性

print(Animal.__x)
print(Dog.__x)
print(a.__x)
print(d.__x)
#4条都会报错,在外部不可以访问私有属性
  • 结论:私有属性在本模块的其他位置都不可以访问,不管通过类、子类、类或子类的实例,都不可以访问到。

  • 只可以在类的内部访问到。

  • 可以访问,但是会有警报,建议不要访问

  • what about跨模块访问?
    ——情况和一个下划线的一致。

你可能感兴趣的:(【python】学习面向对象编程(二))