Post

Python基础概念补齐(持续更新)

self、cls、@staticmethod和@classmethod的区别 1. self vs C# 的 this class Dog: def __init__(self, name): self.name = name # self 代表"哪只狗"

先搞技术 阅读 0 点赞 0 评论 0

self、cls、@staticmethod和@classmethod的区别

1. self vs C# 的 this

class Dog:
    def __init__(self, name):
        self.name = name          # self 代表"哪只狗"

    def bark(self):               # 普通方法,第一个参数是 self
        print(f"{self.name}: 汪汪!")

a = Dog("旺财")
b = Dog("小白")
a.bark()  # 旺财: 汪汪!  ← self 就是 a
b.bark()  # 小白: 汪汪!  ← self 就是 b
class Dog
{
    public string Name;

    public Dog(string name)
    {
        this.Name = name;         // this 代表"哪只狗"
    }

    public void Bark()
    {
        Console.WriteLine($"{this.Name}: 汪汪!");
    }
}

var a = new Dog("旺财");
var b = new Dog("小白");
a.Bark();  // 旺财: 汪汪!  ← this 就是 a
b.Bark();  // 小白: 汪汪!  ← this 就是 b

💡 Python 的 self 必须写在方法参数里,C# 的 this 是隐式的。

2. @classmethod 和 cls

class Dog:
    def __init__(self, name):
        self.name = name          # self 代表"哪只狗"

    def bark(self):               # 普通方法,第一个参数是 self
        print(f"{self.name}: 汪汪!")

a = Dog("旺财")
b = Dog("小白")
a.bark()  # 旺财: 汪汪!  ← self 就是 a
b.bark()  # 小白: 汪汪!  ← self 就是 b
class Dog
{
    public static string Species = "犬科";  // 静态字段,所有狗共享

    public string Name;                      // 实例字段,每只狗不同

    public static string GetSpecies()        // C# 的 static 方法 ≈ Python 的 @classmethod
    {
        return $"我们都是{Species}";
    }
}

Console.WriteLine(Dog.GetSpecies());  // 我们都是犬科

💡 C# 里没有 cls 的概念,用 static 方法 + 类名访问静态成员来实现类似效果。

3. @classmethod 的工厂方法(子类继承时 cls 的妙处)

class Animal:
    @classmethod
    def create(cls, name):
        return cls(name)      # cls 会自动变成调用它的那个类

class Dog(Animal):
    pass

class Cat(Animal):
    pass

dog = Dog.create("旺财")     # cls = Dog,返回 Dog 实例
cat = Cat.create("咪咪")     # cls = Cat,返回 Cat 实例

print(type(dog))  # <class 'Dog'> ✅
print(type(cat))  # <class 'Cat'> ✅

class Animal
{
    public string Name;

    public Animal(string name)
    {
        Name = name;
    }

    // C# 没有 cls,但可以用泛型实现类似效果
    public static T Create<T>(string name) where T : Animal
    {
        return (T)Activator.CreateInstance(typeof(T), name);
    }
}

class Dog : Animal { public Dog(string name) : base(name) { } }
class Cat : Animal { public Cat(string name) : base(name) { } }

var dog = Animal.Create<Dog>("旺财");   // 返回 Dog 实例
var cat = Animal.Create<Cat>("咪咪");   // 返回 Cat 实例

Console.WriteLine(dog.GetType());  // Dog ✅
Console.WriteLine(cat.GetType());  // Cat ✅

4. @staticmethod vs C# 的 static

class Calculator:
    @staticmethod
    def add(a, b):          # 没有 self,也没有 cls
        return a + b

# 直接用类名调用,不需要实例
result = Calculator.add(1, 2)  # 3

class Calculator
{
    public static int Add(int a, int b)   // 没有 this
    {
        return a + b;
    }
}

// 直接用类名调用,不需要实例
int result = Calculator.Add(1, 2);  // 3

💡 C# 的 static 和 Python 的 @staticmethod 几乎一模一样。

5. 三者对比

class Demo:
    class_var = "我是类变量"

    def __init__(self):
        self.instance_var = "我是实例变量"

    def normal_method(self):
        # 能访问:self(实例)、类
        print("普通方法", self.instance_var)

    @classmethod
    def class_method(cls):
        # 能访问:cls(类)、类变量
        # 不能访问:self(实例变量)
        print("类方法", cls.class_var)

    @staticmethod
    def static_method():
        # 不能访问:self、cls
        # 就是个普通函数,放在类里只是为了组织代码
        print("静态方法")

class Demo
{
    public static string ClassVar = "我是类变量";

    public string InstanceVar = "我是实例变量";

    public void NormalMethod()              // 普通方法 ≈ Python 的 self
    {
        Console.WriteLine($"普通方法 {InstanceVar}");
    }

    public static void ClassMethod()        // 静态方法 ≈ Python 的 @classmethod
    {
        Console.WriteLine($"类方法 {ClassVar}");
        // 不能访问 InstanceVar(需要实例)
    }

    public static void StaticMethod()       // 静态方法 ≈ Python 的 @staticmethod
    {
        Console.WriteLine("静态方法");
    }
}

对比项

Python @staticmethod

Python @classmethod

Python 普通方法

C# static

C# 普通方法

第一个参数

cls(类)

self(实例)

this(隐式)

能访问类变量?

能访问实例变量?

需要实例化?

子类继承适配?

@staticmethod和@classmethod的区别总结

@staticmethod:

UserResponse.success()

代码里写的是 Response()

永远返回 Response ← 不管谁调用,结果一样

@classmethod:

UserResponse.success()

cls 自动变成 UserResponse

返回 UserResponse ← 谁调用就返回谁的类型

@staticmethod → 永远用父类(写死了)

@classmethod → 用当前调用它的子类本身(自动适配)

就这一个区别,记住就够了。👍

评论