前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python语法-类与实例

Python语法-类与实例

作者头像
码客说
发布2021-11-29 09:20:15
5280
发布2021-11-29 09:20:15
举报
文章被收录于专栏:码客

类定义

代码语言:javascript
复制
class Person:
  def __init__(self, name, age):
    self.name = name
    self.age = age

  def myfunc(self):
    print("Hello my name is " + self.name)

p1 = Person("Bill", 63)
p1.myfunc()

属性

类属性

代码语言:javascript
复制
class Person:
    name = "person"

    def __init__(self, name, age):
        self.name = name
        self.age = age


p1 = Person("Bill", 63)
print(Person.name)
print(p1.name)

结果

代码语言:javascript
复制
person
Bill

getattr/getattribute

代码语言:javascript
复制
class User:
    def __getattribute__(self, item):
        if (item == "age"):
            return 0

    def __getattr__(self, item):
        if (item == "age"):
            return 99

私有属性

代码语言:javascript
复制
class Person:
    def __init__(self, name, age):
        self.__name = name
        self.age = age

    def getName(self):
        return self.__name


p1 = Person("Bill", 63)
print(p1.age)
print(p1.getName()) # 可以通过方法访问
print(p1._Person__name) # 这种方式依旧可以访问
print(p1.__name)  # 这种方式是访问不了的

动态属性

代码语言:javascript
复制
class Person:

    def __init__(self, name, age):
        self.name = name
        self.age = age

    @property
    def sex(self):
        return "男"


p1 = Person("小明", 63)
print(p1.name)
print(p1.sex)

结果

代码语言:javascript
复制
小明
男

可以看出

动态属性就和vue的计算属性一样,可以像访问属性一样访问方法。

数据描述符/非数据描述符

代码语言:javascript
复制
import numbers


# 数据描述符
class IntField:
    def __get__(self, instance, owner):
        return self.value

    def __set__(self, instance, value):
        if not isinstance(value, numbers.Integral):
            raise ValueError("need int value")
        self.value = value

    def __delete__(self, instance):
        pass


# 非数据描述符
class NoDataField:
    def __get__(self, instance, owner):
        return 4


class User:
    age = IntField()


if __name__ == "__main__":
    u = User()
    u.age = 10

这样如果赋值的时候不是数字,就会报错

这样就可以限制参数的类型了。

获取属性的顺序

获取属性的两种方式

代码语言:javascript
复制
u = User()
u.age
# 等效于
getattr(u, "age")

获取属性的优先级顺序

  1. 调用__getattribute__
  2. 类或者基类中定义的数据描述符
  3. 实例中的属性 user.__dict__["age"]
  4. 中的非数据描述符
  5. 类或基类的属性 User.__dict__["age"]
  6. 调用中的__getattr__方法
  7. 抛出AttributeError

查看实例的属性

代码语言:javascript
复制
class User:
    def __init__(self, name, age):
        self.__name = name
        self.age = age


u = User("小明", 16)
print(u.__dict__)  # 查看实例的属性
print(dir(u))  # 只能看属性的名称,不能看值,但是看到的属性比较全
print(User.__dict__)  # 查看类的属性
print(dir(User))  # 查看类的属性

结果

代码语言:javascript
复制
{'_User__name': '小明', 'age': 16}
['_User__name', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'age']
{'__module__': '__main__', '__init__': <function User.__init__ at 0x017BD100>, '__dict__': <attribute '__dict__' of 'User' objects>, '__weakref__': <attribute '__weakref__' of 'User' objects>, '__doc__': None}
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']

类与对象

代码语言:javascript
复制
class User:
    def __new__(cls, *args, **kwargs):
        return super().__new__(cls, *args, **kwargs)

    def __init__(self, name, age):
        self.__name = name
        self.age = age


u = User("小明", 16)
print(getattr(u, "age"))

注意

__new__是用来把类生成对象,实在创建对象之前调用,如果没有返回,则__init__不会调用。 __init__是用来给对象初始化属性的。

方法

实例方法

代码语言:javascript
复制
class Person:

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def get_age(self):
        return self.age


p1 = Person("小明", 63)
print(p1.get_age())

静态方法

代码语言:javascript
复制
class Person:
    def __init__(self, name, age):
        self.__name = name
        self.age = age

    @staticmethod
    def getName():
        return "123"


print(Person.getName())  # 可以通过方法访问
p1 = Person("Bill", 63)
print(p1.getName())  # 可以通过方法访问

注意

静态方法可以用类调用,也可以用示例调用。

类方法

代码语言:javascript
复制
class Person:

    def __init__(self, name, age):
        self.name = name
        self.age = age

    @classmethod
    def getPerson(cls, name, age):
        return cls(name, age)


p1 = Person.getPerson("小明", 63)
print(p1.name)

注意

类方法的主要好处在于生成类的实例的时候不用写类名,这样一旦类名发生变化,类方法中不用修改代码。

判断为空

代码语言:javascript
复制
if (p1 is None):

判断是否是类的实例

代码语言:javascript
复制
class Person:

    def __init__(self, name, age):
        self.name = name
        self.age = age


p1 = Person("小明", 63)
print(isinstance(p1, Person))

删除属性或对象

代码语言:javascript
复制
a = object()
b = a
del a
print(b)
print(a)

结果

代码语言:javascript
复制
<object object at 0x017265B0>
Traceback (most recent call last):
  File "main.py", line 5, in <module>
    print(a)
NameError: name 'a' is not defined

我们会发现a被删除后,b依旧没有被销毁,这是因为对应每次被引用都会计数器+1,只有计数器为0,才会销毁。

继承

代码语言:javascript
复制
class Student(Person):

Python的类是可以多继承的

代码语言:javascript
复制
class C(A,B):

注意

开发时尽量不要用多继承

super

基本使用

代码语言:javascript
复制
class A:
    def __init__(self) -> None:
        print("A")


class B(A):
    def __init__(self) -> None:
        super().__init__()
        print("B")


if __name__ == "__main__":
    b = B()

结果

代码语言:javascript
复制
A
B

调用的顺序

代码语言:javascript
复制
class A:
    def __init__(self) -> None:
        print("A")
        super().__init__()


class B(A):
    def __init__(self) -> None:
        print("B")
        super().__init__()


class C(A):
    def __init__(self) -> None:
        print("C")
        super().__init__()


class D(B, C):
    def __init__(self) -> None:
        print("D")
        super().__init__()


print(D.__mro__)
d = D()

结果

代码语言:javascript
复制
(<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
D
B
C
A

可以看出

调用顺序是按照MRO的算法来调用的 使用类.__mro__可以查看调用顺序 属性和方法都是这个规则

抽象类

代码语言:javascript
复制
import abc


class A(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def say(self):
        pass


class B(A):
    def __init__(self):
        pass

    def say(self):
        pass


if __name__ == "__main__":
    b = B()

注意

如果B不实现A的抽象方法就会报错。

动态创建类

代码语言:javascript
复制
def create_class01(ctype):
    if (ctype == "user"):
        class User:
            name = "小明"

            def say(self):
                print(f"{self.name} say")

        return User


def create_class02(ctype):
    def say(self):
        print(f"{self.name} say")

    if (ctype == "user"):
        User = type("User", (), {"name": "小明", "say": say})
        return User


if __name__ == "__main__":
    User = create_class02("user")
    u = User()
    print(u.name)
    u.say()

结果

代码语言:javascript
复制
小明
小明 say
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-11-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 类定义
  • 属性
    • 类属性
      • getattr/getattribute
        • 私有属性
          • 动态属性
            • 数据描述符/非数据描述符
              • 获取属性的顺序
                • 查看实例的属性
                • 类与对象
                • 方法
                  • 实例方法
                    • 静态方法
                      • 类方法
                        • 判断为空
                          • 判断是否是类的实例
                            • 删除属性或对象
                            • 继承
                              • super
                                • 基本使用
                                • 调用的顺序
                            • 抽象类
                            • 动态创建类
                            领券
                            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档