Python __repr__ 方法:编写等效的 JS 方法?

发布于 2025-01-15 09:17:28 字数 1813 浏览 2 评论 0原文

我正在学习关于算法和数据结构的简短初学者课程。讲师的语言是Python;我正在将代码示例转换为 JavaScript。到目前为止,一切都很好。

我正在处理链接列表。讲师使用 Python 的 __repr__() 方法测试代码。经过几天的反复试验,我有了一个可行的 JS 解决方案,但它与 Python 代码并不完全相同。我想知道是否有更好的方法来实现我提供的 JS 代码以及 Python 代码。

Python

# class LinkedList and its methods are presumed to exist

def __repr__(self):
  
  nodes = []
  current = self.head

  while current:
    if current is self.head:
      nodes.append("[Head: %s]" % current.data)
    elif current.next_node is None:
      nodes.append("[Tail: %s]" % current.data)
    else
      nodes.append("[%s]" % current.data)

    current = current.next_node
  return '-> '.join(nodes)

# running script
>>> l = LinkedList()
>>> l.add(1)
>>> l.add(2)
>>> l.add(3)
>>> l
[Head: 3]-> [2]-> [Tail: 1]  # output
>>>

JS

// class LinkedList and its methods are presumed to exist

repr () {
  
  let nodes = "";
  let current = this.head;

  while (current) {
    if (current === this.head) {
      nodes = `Head: ${current.data}-> `;
    } else if (current.nextNode === null) {
      nodes += `Tail: ${current.data}`;
    } else {
      nodes += `${current.data}-> `;
    }
    current = current.nextNode;
  }
  return nodes;

// running the script
let l = LinkedList();
l.add(1);
l.add(2);
l.add(3);

let result = l.repr();
console.log(result);  // Head: 3-> 2-> Tail: 1

同样,这两个片段只能在链表算法的完整实现中运行,但它们确实可以工作。

我的尝试:我尝试使用JS toString()append()appendChild(),但它们对我来说太难了了解如何最好地使用它们,特别是当最后两个修改 DOM 时。我确信有更好的方法来实现相当于 Python __repr__(); 的 JS 方法。我想知道如何做到这一点。

I am working through a short beginner's course on Algorithms and Data Structures. The instructor's language is Python; I am converting the code examples to JavasScript. So far, so good.

I am dealing with Linked Lists. The instructor tests the code using Python's __repr__() method. After days of trial and error, I have a working JS solution, but it is not exactly the same as the Python code. I would like to know if there is a better way of implementing the JS code, which I provide, along with the Python code.

Python

# class LinkedList and its methods are presumed to exist

def __repr__(self):
  
  nodes = []
  current = self.head

  while current:
    if current is self.head:
      nodes.append("[Head: %s]" % current.data)
    elif current.next_node is None:
      nodes.append("[Tail: %s]" % current.data)
    else
      nodes.append("[%s]" % current.data)

    current = current.next_node
  return '-> '.join(nodes)

# running script
>>> l = LinkedList()
>>> l.add(1)
>>> l.add(2)
>>> l.add(3)
>>> l
[Head: 3]-> [2]-> [Tail: 1]  # output
>>>

JS

// class LinkedList and its methods are presumed to exist

repr () {
  
  let nodes = "";
  let current = this.head;

  while (current) {
    if (current === this.head) {
      nodes = `Head: ${current.data}-> `;
    } else if (current.nextNode === null) {
      nodes += `Tail: ${current.data}`;
    } else {
      nodes += `${current.data}-> `;
    }
    current = current.nextNode;
  }
  return nodes;

// running the script
let l = LinkedList();
l.add(1);
l.add(2);
l.add(3);

let result = l.repr();
console.log(result);  // Head: 3-> 2-> Tail: 1

Again, the two fragments will only run in a full implementation of the Linked List algorithm, but they do work.

Attempts I have made: I tried to use JS toString(), append() and appendChild(), but they were too difficult for me to understand how best to use them, particularly as the last two modify the DOM. I'm sure there is a better way of implementing a JS equivalent of the Python __repr__(); I would like to know how it might be done.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

又怨 2025-01-22 09:17:28

更接近的实现将使用 toString 方法。当需要转换为字符串时,会隐式调用此方法。 Python 实际上有两种方法可以实现此目的,它们的用途略有不同:__repr____str__。 JavaScript 中没有这样的区别。

此外,我们应该意识到Python的print将隐式调用__repr__,这不是console.log的工作方式。因此,对于console.log,您必须强制转换为字符串。

以下是给定 Python 代码的最字面翻译方式(我添加了运行脚本所需的类):

class Node {
    constructor(data, next=null) {
        this.data = data;
        this.next_node = next;
    }
}

class LinkedList {
    constructor() {
        this.head = null;
    }
    add(data) {
        this.head = new Node(data, this.head);
    }
    toString() {
        let nodes = [];
        let current = this.head;
        while (current) {
            if (current === this.head) {
                nodes.push(`[Head: ${current.data}]`);
            } else if (current.next_node === null) {
                nodes.push(`[Tail: ${current.data}]`);
            } else {
                nodes.push(`[${current.data}]`);
            }
            current = current.next_node;
        }
        return nodes.join('-> ');
    }
}

// running script
let l = new LinkedList();
l.add(1);
l.add(2);
l.add(3);
// Force conversion to string
console.log(`${l}`); // [Head: 3]-> [2]-> [Tail: 1]

就我个人而言,我会进行以下更改(未反映在 Python 版本中):

  • 生成不带“Head”和“Tail”以及其他“装饰”字样的输出。这对我来说太冗长了。只需输出分离的值即可。
  • 使列表实例可迭代,实现 Symbol.iterator 方法(在 Python 中:__iter__)。然后使用它来实现 toString 方法。
  • 允许列表构造函数采用任意数量的值来填充列表。

这导致以下版本:

class Node {
    constructor(data, next=null) {
        this.data = data;
        this.next = next;
    }
}

class LinkedList {
    constructor(...values) { // Accept any number of values
        this.head = null;
        // Populate in reverse order
        for (let data of values.reverse()) this.add(data);
    }
    add(data) {
        this.head = new Node(data, this.head);
    }
    // Make lists iterable
    *[Symbol.iterator]() {
        let current = this.head;
        while (current) {
            yield current.data;
            current = current.next;
        }
    }
    toString() {
        // Array.from triggers the above method
        return Array.from(this).join("→");
    }
}

// Provide the desired values immediately:
let l = new LinkedList(3, 2, 1);
console.log(`${l}`); // 3→2→1

A closer implementation would use a toString method. This method is called implicitly when a conversion to string is needed. Python has actually two methods for this, which have a slightly different purpose: __repr__ and __str__. There is no such distinction in JavaScript.

Furthermore, we should realise that Python's print will implicitly call __repr__, which is not how console.log works. So with console.log you'd have to enforce that conversion to string.

Here is how the given Python code would be translated most literally (I add the classes needed to run the script):

class Node {
    constructor(data, next=null) {
        this.data = data;
        this.next_node = next;
    }
}

class LinkedList {
    constructor() {
        this.head = null;
    }
    add(data) {
        this.head = new Node(data, this.head);
    }
    toString() {
        let nodes = [];
        let current = this.head;
        while (current) {
            if (current === this.head) {
                nodes.push(`[Head: ${current.data}]`);
            } else if (current.next_node === null) {
                nodes.push(`[Tail: ${current.data}]`);
            } else {
                nodes.push(`[${current.data}]`);
            }
            current = current.next_node;
        }
        return nodes.join('-> ');
    }
}

// running script
let l = new LinkedList();
l.add(1);
l.add(2);
l.add(3);
// Force conversion to string
console.log(`${l}`); // [Head: 3]-> [2]-> [Tail: 1]

Personally, I would make the following changes (not reflected in the Python version):

  • Produce output without the words "Head" and "Tail" and other "decoration". This is too verbose to my liking. Just output the separated values.
  • Make list instances iterable, implementing the Symbol.iterator method (In Python: __iter__). Then use this for implementing the toString method.
  • Allow the list constructor to take any number of values with which the list should be populated.

This leads to the following version:

class Node {
    constructor(data, next=null) {
        this.data = data;
        this.next = next;
    }
}

class LinkedList {
    constructor(...values) { // Accept any number of values
        this.head = null;
        // Populate in reverse order
        for (let data of values.reverse()) this.add(data);
    }
    add(data) {
        this.head = new Node(data, this.head);
    }
    // Make lists iterable
    *[Symbol.iterator]() {
        let current = this.head;
        while (current) {
            yield current.data;
            current = current.next;
        }
    }
    toString() {
        // Array.from triggers the above method
        return Array.from(this).join("→");
    }
}

// Provide the desired values immediately:
let l = new LinkedList(3, 2, 1);
console.log(`${l}`); // 3→2→1

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文