TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

New Ways to Be Told That Your Python Code Is Bad

102 pointsby nickdrozdover 3 years ago

48 comments

MathMonkeyManover 3 years ago
Ah, leave people alone.<p>I stopped using ternary expressions because someone told me not to. I could start using them again, whatever.<p>I use while loops when the burden of describing the loop as an iteration is too high (too much of a stretch), or when I&#x27;m writing something that really isn&#x27;t a composition of forEach&#x2F;map&#x2F;filter&#x2F;reduce (gasp).<p>For me, it&#x27;s whatever I need to do to get through code review without arguing too much.<p>Don&#x27;t add linter checks for these things, it&#x27;s condescending.<p>At the very least, have the &quot;greater good&quot; on your side, e.g. &quot;it confuses some people!&quot; or &quot;it is often a bug!&quot; or &quot;it can become a maintenance nightmare!&quot; or whatever. If your reason is &quot;I like it better this way,&quot; well then yeah, the reaction I would anticipate is &quot;who asked you?&quot;<p>The reason this bothers me isn&#x27;t that I strongly disagree, but that I&#x27;m in the habit of doing whatever my linter tells me, and adding stuff like this cheapens the thing and makes it harder to sell to &quot;I&#x27;m an expert, get off my lawn&quot; people.<p>Why am I even writing this, I&#x27;m knee deep in C++ these days.
评论 #28402899 未加载
评论 #28404337 未加载
评论 #28407605 未加载
评论 #28402399 未加载
评论 #28404331 未加载
评论 #28404618 未加载
评论 #28408483 未加载
ohaziover 3 years ago
&gt; Python programmers in general have an irrational aversion to if-expressions, a.k.a. the “ternary” operator.<p>Because the Python ternary operator is fucking backwards! Why on earth would you put the condition in the <i>middle</i>!?<p><pre><code> x = 4 if condition() else 5 </code></pre> vs.:<p><pre><code> condition() ? 4 : 5 </code></pre> vs. the author&#x27;s own lisp example:<p><pre><code> (setq x (if (condition) 4 5)) </code></pre> I love ternary operators, and Lisp&#x2F;ML-style if else blocks that return things, but Python puts the 4 and the 5 so far away from each other that even I hate using it, especially when condition is a chained mess rather than just a function call.
评论 #28403136 未加载
评论 #28403065 未加载
评论 #28402047 未加载
评论 #28402306 未加载
评论 #28401958 未加载
评论 #28402376 未加载
评论 #28402815 未加载
评论 #28405217 未加载
评论 #28402655 未加载
评论 #28402904 未加载
评论 #28401979 未加载
评论 #28403127 未加载
评论 #28401765 未加载
Zababaover 3 years ago
I really hope that the condescending tone of the article was because the author was tired or something, and that it&#x27;s not the attitude they use when contributing to a linter. The authors comes out as arrogant and self-centered, the &quot;reactions&quot; are strawmans, the tone is aggressive.<p>Sure that nice Beeping Busy Beaver uses only one loop, very cool. The &quot;guessing game&quot; program that almost everyone wrote when learning programming also uses one loop.<p>I&#x27;ll now go work on my linter for blog posts that forbids using bold text. The Bible didn&#x27;t use any bold text, so why would a simple blog post need it?
评论 #28401437 未加载
评论 #28401893 未加载
评论 #28401075 未加载
chriswarboover 3 years ago
&gt; Anyway, this is just a style thing. It doesn’t affect program correctness or structure in a meaningful way.<p>The nice thing about ternaries is that they&#x27;re expressions, so they don&#x27;t &quot;infect&quot; our code like statements (e.g. &#x27;if&#x27;). For example:<p><pre><code> if xCond: x = x1 else: x = x2 if yCond: y = y1 else: y = y2 if zCond: z = z1 else: z = z2 foo(x, y, z) </code></pre> This lint rule will tell us to do the following instead:<p><pre><code> x = x1 if xCond else x2 y = y1 if yCond else y2 z = z1 if zCond else z2 foo(x, y, z) </code></pre> Now that our branching is done with expressions rather than statements, we can actually in-line them, which seems much nicer (less chance to get them mixed up; no need to invent new names; no side-effects, e.g. accidentally overwriting an existing variable; etc.)<p><pre><code> foo( x1 if xCond else x2, y1 if yCond else y2, z1 if zCond else z2, ) </code></pre> If we really want the names, we could define them using the &#x27;walrus operator&#x27;:<p><pre><code> foo( x := (x1 if xCond else x2), y := (y1 if yCond else y2), z := (z1 if zCond else z2), ) </code></pre> Personally I would use separate &#x27;x = ...&#x27; statements rather than :=, since we want to explicitly perform effects (binding names).
评论 #28401572 未加载
评论 #28399710 未加载
_ZeD_over 3 years ago
I have problem with both new checkers:<p>regarding the `consider-ternary-expression`<p><pre><code> if condition(): x = 4 else: x = 5 </code></pre> allow me to put f<i>ck&#x27;n breakpoints - in this case the expression is dumb, but what if is some complex stuff?<p><pre><code> x = 4 if condition() else 5 </code></pre> is cute, but - remember, kids - not </i>everything* should be an expression<p>regarding the `while-used`, while I personally prefer the legibility of the `for` loop, I find the following paragraph... at best wrong:<p>&gt;&gt;&gt; A while loop introduces unbounded computation. Do you really need unbounded computation for your boring web app? I doubt it. In almost all cases, the loop can be bounded in advance, as in “do this N times” or “do this for every item in this list”. Those kinds of loops are guaranteed to terminate, and that’s a nice guarantee to have.<p>in python `for` loop are equally unbounded as `while` ones. Yes, most of the time you are looping over a (finite) list or a (finite) dict, but the concept underlying the `for` loop is the iterator, not the list. And iterators can easily be infinite.
评论 #28401973 未加载
zootboyover 3 years ago
&gt; less code is better than more code<p>Not when it&#x27;s at the cost of readability. The example &quot;better&quot; code fails my readability test horribly. I&#x27;d gladly take C&#x27;s ternary operator over this monstrosity:<p>&gt; x = 4 if condition() else 5
评论 #28400654 未加载
评论 #28399476 未加载
评论 #28401767 未加载
评论 #28401155 未加载
评论 #28399567 未加载
评论 #28399533 未加载
评论 #28401107 未加载
评论 #28399592 未加载
评论 #28399367 未加载
评论 #28399591 未加载
评论 #28399655 未加载
评论 #28399717 未加载
rogualover 3 years ago
A lot of bloggers love linters, and they will look for any reason to promote them. They will say things like “programmers don’t like to have their code criticized” and “chicken-little reaction” and other excuses. But fundamentally the problem is that bloggers like to tell others what to do.<p>Well, tough shit, because I closed the tab.
评论 #28403945 未加载
dragonwriterover 3 years ago
&gt; But here’s the reality: most code is not complex enough to warrant while loops, and most while loops are better written as for loops.<p>Hard disagree. Obviously, if the loop is a fixed number of iterations or iteration over a collection (which is trivial to identify by human inspection but probably not for a linter), a for loop is better but it is not uncommon to be looping until a (possibly compound) condition becomes true that cannot be expressed as a fixed number of iterations or (at least naturally; you can embed arbitrary complexity into a generator, though usually, absent unbounded recursion, that will just push the “while” down behind a layer of abstraction) as exhaustion of an iterable.
评论 #28401751 未加载
评论 #28401862 未加载
nine_kover 3 years ago
While I appreciate the idea of bounded loops, it&#x27;s a mistake to think that a `for` loop is necessarily bounded.<p>It&#x27;s pretty easy to write a generator that produces an infinite sequence. That generator, of course, would need a `while` loop, but that loop can be in an external dependency which the linter is not checking.<p>You also can read way more than you expected if you use a `for` loop to read from a socket, or a file, to say nothing about reading from &#x2F;dev&#x2F;random.<p>Not that it&#x27;s a bad advice, but it&#x27;s not a rule, it&#x27;s more like a... guideline. Discretion is still needed.
评论 #28400827 未加载
评论 #28401417 未加载
WesolyKubeczekover 3 years ago
Inspired by the boldness of this article, I decided to make my own linter which was going to be the most opinionated of them all.<p>Since my gut feeling is that 99% of the code is always shit that should not have been written at all, I have coded a linter that simply flags every line of your code and strongly advises you to delete it. And also change your trade if you can.<p>This linter was a very good invention. But then I got caught up in the spirit of being fair and “eating my own dog food”, and ran the ultimate linter on its own code.<p>It told me the code was pathetic shit and that I should delete it, and never write a line of code again because very likely it was going to be same shit, but worse.<p>I followed its advice.
chrismorganover 3 years ago
&gt; <i>A while loop introduces unbounded computation.</i><p>Then so does a for loop. There’s no difference in this regard between for and while loops: you can use both of them to express both bounded and unbounded computations, and in each case you need to read and understand at least what comes before the colon to know which it is.<p><pre><code> # Unbounded while True: pass # Bounded while False: pass # Unbounded for i in itertools.count(): pass # Bounded for x in []: pass </code></pre> And you can’t just say “but with for loops you only need to worry about the iterator, whereas with while loops you’ll probably need to worry about statements inside the loop <i>in addition</i> to the loop condition”, as seen in this entirely realistic function that is unbounded if source == target (assuming a port of the DOM API, so child_nodes is a live collection):<p><pre><code> def clone_children_to(source: Element, target: Element): for node in source.child_nodes: target.append_child(node.clone()) </code></pre> (I agree that for loops are generally preferable to while loops where feasible, but I object to the way you’ve expressed that paragraph, and the <i>expressed</i> reasoning underpinning the entire section is flawed, as priansh also points out.)
jimmaswellover 3 years ago
I have a much better time with Python just doing what I want instead of following the Python community&#x27;s sometimes arbitrary and capricious standards.
评论 #28401459 未加载
评论 #28399570 未加载
devneyover 3 years ago
I just feel like this author could have chosen a better example. The if&#x2F;else block that he complains about is easy to read and simple to understand. The ternary he advises raises the bar significantly for anyone trying to read the code, while having no practical effect on runtime or usability.<p>Based on my 25+ years of experience I strongly believe that the &quot;if&#x2F;else&quot; that this author complains about is actually BETTER than the ternary he recommends. This is yet another example of the endemic problem where software engineers think &quot;harder to read is a virtue&quot;.
lmmover 3 years ago
If expressions are good, but <i>python&#x27;s</i> hideous middle-endian if expressions are rightfully feared.
markragesover 3 years ago
Python doesn&#x27;t have a do..while loop, so when you want to do a thing at least once, the simplest replacement is starting the loop with &quot;while 1:&quot; and ending the loop with &quot;if ... break&quot;.<p>I disapprove of any linter that flags this idiom.
评论 #28401809 未加载
评论 #28399673 未加载
empikoover 3 years ago
People raging over the ternary operation in Python should learn to use:<p><pre><code> x = {True: 5, False: 4}[condition()] </code></pre> , or if you don&#x27;t want to evaluate the values:<p><pre><code> x = {True: lambda: 5, False: lambda: 4}[condition()]()</code></pre>
评论 #28401985 未加载
评论 #28402233 未加载
评论 #28401315 未加载
评论 #28404399 未加载
评论 #28401270 未加载
tpoacherover 3 years ago
Well, he&#x27;s right that it&#x27;s opinionated. If I were to contribute to that project I&#x27;d opinionatedly implement the exact <i>opposite</i> linter, suggesting proper if blocks instead of a ternary expression.<p>The reason is simple: visual code structure.<p>A bespoke if block provides you with appropriate visual semantics that that part of the code involves a decision point.<p>By contrast, the ternary operator is useful when you want to visually obfuscate that fact, and make the code terser and more focused on the fact that an assignment is taking place, whose value is determined by an expression (which upon closer inspection happens to be conditional).<p>Yes I know that in the age of super-fat IDEs everything is but a search away, but, I&#x27;ve just come off from reading that other article from today about the guy who handwrites all his code.<p>So clearly low-level visual structure and ease of mental debugging still matters, no matter <i>how</i> bloated and feature-full your IDE is.<p>But what do I know. I still code on vim&#x2F;nano.
评论 #28402653 未加载
ChrisMarshallNYover 3 years ago
I love linters.<p>This is one of the first things that I add to a new project, before I write one line of code: <a href="https:&#x2F;&#x2F;github.com&#x2F;realm&#x2F;SwiftLint" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;realm&#x2F;SwiftLint</a><p>I write about it here: <a href="https:&#x2F;&#x2F;littlegreenviper.com&#x2F;miscellany&#x2F;swiftwater&#x2F;swiftlint&#x2F;" rel="nofollow">https:&#x2F;&#x2F;littlegreenviper.com&#x2F;miscellany&#x2F;swiftwater&#x2F;swiftlint...</a>
评论 #28399638 未加载
yongjikover 3 years ago
&gt; You know what else doesn’t have unbounded loops? Excel.<p>Right, one of the many reasons why nobody (with half a brain) hosts a web server in Excel.<p>I wonder how much &quot;boring web app&quot; experience the author had. If I&#x27;m debugging on 11 pm why the webserver is timing out talking to microservice A, but only if it first opened connection to service B, and someone strolls along saying &quot;Hey, your code is bad because it&#x27;s using unbounded computation,&quot; then god help us, because I might lose it. (Well, shrug, the worst that can happen is that I may rage-quit on the spot. I&#x27;m not a very imposing guy.)
评论 #28400870 未加载
评论 #28401090 未加载
评论 #28401059 未加载
scytheover 3 years ago
&gt;most code is not complex enough to warrant while loops,<p><pre><code> scale = 5 while (scale &gt; 0.1): do_stuff(scale) scale = scale&#x2F;2 </code></pre> Sure, you could use exponentials with range(), but is that really clearer?
评论 #28399676 未加载
评论 #28400809 未加载
评论 #28399887 未加载
prianshover 3 years ago
While I agree with the ternary linting, the while loop piece makes absolutely no sense. There are absolutely many, many use cases of while loops; in fact, many dynamic programming algorithms rely on them.<p>Could you write them as a for loop? Possibly, but why? Is the new 2021 programming fad hating on while loops? Who do I contact to exchange my &quot;js bad&quot; t-shirts for &quot;while bad&quot; laptop stickers?<p>The logic behind disapproving of while loops in the article seems to stem from the author assuming while loops are &quot;unbounded.&quot; This is absolutely, completely, totally false and there are entire branches of reasoning dedicated towards observing the bounded-ness of while loops. Most colleges include this in their curriculums and you usually have to learn to prove (via induction) the variants and invariants surrounding your loop before you can pass basic classes. It&#x27;s even more ridiculous that, in the same breath, the author assumes for loops are guaranteed to complete execution. I can disprove this in two lines of code and two braincells:<p><pre><code> for x in infinite_generator(): do_something() </code></pre> This is also the general structure that message-queue libraries like Kafka, RabbitMQ etc take with their python code. Not to mention that, in many programming languages, for-loops are actually implemented as while loops behind the scenes.<p>I&#x27;ll cede that it&#x27;s easier to write unbounded code with while loops than for loops, but this is programmer error that can be pretty easily avoided by simply being a teensy tiny bit careful (and can be easily corrected). I&#x27;d also argue that the majority of these cases where while loops can be substituted by for loops, are also cases where writing a while loop is much simpler than trying to convert into a for loop. (Besides, you could make any of these arguments about recursion.)<p>&gt; You know what else doesn’t have unbounded loops? Excel.<p>This is also a lie, Excel absolutely has infinite loops, it just yells at you when you do it. The equivalent of this in programming is a linter. Instead of just screaming fire every time the user writes a perfectly fine while loop, why not concentrate your efforts on identifying unbounded loops and introducing a linter rule for that?<p>Honestly, it&#x27;s absolutely terrifying to me that someone contributing to the predominant linter for a major programming language not only wholeheartedly believes while loops are always unbounded and usually evil, but also managed to get this introduced (and presumably approved) by reviewers of this linter, and then proceeded to gloat about it on HackerNews. It comes as no shock to me that most people I&#x27;ve worked with disable pylint in their editors if they&#x27;re this unreliable with their review process.
评论 #28399913 未加载
mfgsover 3 years ago
&quot;it unconditionally flags every use of while expressions.&quot;<p>I&#x27;d find that pretty annoying.<p>Consider a while loop in a thread:<p><pre><code> while not quit_thread_requested: # do threaded task</code></pre>
评论 #28399601 未加载
评论 #28399557 未加载
arusahniover 3 years ago
FWIW, ternary expressions aren&#x27;t properly detected by coverage: <a href="https:&#x2F;&#x2F;github.com&#x2F;nedbat&#x2F;coveragepy&#x2F;issues&#x2F;509" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;nedbat&#x2F;coveragepy&#x2F;issues&#x2F;509</a>
SkipperCatover 3 years ago
Tools that enforce &quot;expert level&quot; coding standards do make code more concise, but also less comprehendible for the less experienced developers. I never saw the harm in four lines of code instead of one, especially when it&#x27;s much more readable.
评论 #28399709 未加载
评论 #28399470 未加载
评论 #28399543 未加载
评论 #28399741 未加载
fhoover 3 years ago
Some (including me) would argue that writing any loop yourself is considered harmful and you should be better of using higher order functions.<p>In Haskell there is a higher order function for basically every usecase and (most of the time) the compiler is smart enough to merge chained higher order functions into a single loop.<p>Python is at least trying with its `itertools` package, but it&#x27;s still a far cry from the generalization &quot;modern&quot; languages allow.<p>(Background: I was fortunate enough to program in Haskell for 2 years. It was great, but I can see that it&#x27;s basically useless for a lot of common usecases :-( )
评论 #28403360 未加载
评论 #28404748 未加载
H8crilAover 3 years ago
The author mentioned this at the end, but banning while loops (and any other way for running a loop with a priori unknown number of iterations) actually decreases the expressiveness of a language - it becomes no longer Turing complete. A classic example is the Ackerman function - it cannot be computed in a primitive recursive language.<p>(The author is on point when they say almost all code used in practice is primitive recursive, though)
评论 #28399686 未加载
评论 #28399711 未加载
greenie_beansover 3 years ago
I’m ~intermediate at python and understand the arguments in this article, but the comments are so negative and varied that i don’t know how to make sense of the contrary. Could somebody please share some more advanced resources about while loops&#x2F;for loops&#x2F;iterables, or point me in the right direction?
评论 #28408009 未加载
dijitover 3 years ago
Unbounded computation is necessary when working on either event driven architecture (block&#x2F;wait for something, run it, block&#x2F;wait again) or working with frames.<p>I can’t imagine making a game (though not sure who makes games in python) without a while loop to run on the main thread.
评论 #28401562 未加载
kristapsover 3 years ago
The ootb linter setups I&#x27;ve seen offer little useful checks, just everybodies feelings about your code, so personally don&#x27;t find them useful. This article is a prrfect example of that, but kudos to the author for being honest about it.
mannykannotover 3 years ago
Claiming that the &#x27;too many false positives&#x27; objection is just an excuse for not liking having one&#x27;s code criticized is itself just an excuse for dismissing a real problem with linters. When writing code from scratch, I am generally eager to use static checking, but when I am flooded with complaints about things I cannot reasonably do anything about, it becomes useless.<p>...And I wrote &#x27;generally eager&#x27;, because having a linter raise pedantic concerns over trivial matters is a way to extend this problem across from-scratch code as well.
syatsover 3 years ago
I always had the vague impression that the original purpose of linters was for some arrogant ahole to impose his &quot;style&quot; on other people. Now I have confirmed this impression.
QuadrupleAover 3 years ago
So is the author suggesting that a while loop like this:<p><pre><code> while not quitRequested: processNextEvent() </code></pre> Should be rewritten to this?<p><pre><code> for i in range(999999): if quitRequested: break processNextEvent() </code></pre> Because that&#x27;s supposedly guaranteed to halt? If so he&#x27;s either joking or crazy. And his program will crash for his poor users after 999999 events.
评论 #28400938 未加载
评论 #28400750 未加载
评论 #28402062 未加载
dethosover 3 years ago
Is this a joke, right?<p><pre><code> Do you really need unbounded computation for your boring web app? </code></pre> Because everyone using python is working on web application. Also because all web applications have the same type of business logic.<p>I do like linters, the best ones help avoiding mistakes and ensure some consistency in the codebase, but this article goes a bit too far.
l0b0over 3 years ago
Sure, once you cherry-pick the most trivial imaginable example ternary expressions are easy enough to read. First counter-example which came to mind:<p><pre><code> print(&quot;yes&quot;) if random.choice([True, False]) else print(&quot;no&quot;) </code></pre> Does this do the right thing? I was pleasantly surprised to find that this is indeed lazily evaluated, but that&#x27;s not at all intuitive: first because `print(&quot;yes&quot;)` comes <i>before</i> the conditional (note that the Lisp example had the conditional first), and second because not all popular languages work like that.<p>There are lots of examples where ternary makes things obviously harder to read, such as when at least two of the three expressions are non-trivial. Which one would you rather read?<p><pre><code> if some_complex_condition(using, four, different, parameters): do_a_thing(now, using, five, different, parameters) else: do_another_thing(with, three, parameters) </code></pre> or<p><pre><code> do_a_thing(now, using, five, different, parameters) if some_complex_condition(using, four, different, parameters) else do_another_thing(having, three, parameters) </code></pre> (or<p><pre><code> do_a_thing(now, using, five, different, parameters) if some_complex_condition( using, four, different, parameters ) else do_another_thing(having, three, parameters) </code></pre> after Black.)
评论 #28399462 未加载
评论 #28401077 未加载
评论 #28399650 未加载
lelanthranover 3 years ago
&gt; Python programmers in general have an irrational aversion to if-expressions<p>If that&#x27;s the case, maybe the problem is the if-expression, and not the programmers?<p>If you have a syntactical construct in your language that the programmers are avoiding in general, then that construct has problems.
w_t_payneover 3 years ago
Linters are good because they stop people arguing. Some early employee in the team defines some set of rules, and that&#x27;s just the way things are from then onwards.<p>Less time bickering means more time spent doing actual productive stuff.
评论 #28402981 未加载
rubyist5evaover 3 years ago
I don’t agree with these opinionated defaults, but I’m primarily a Ruby programmer so my tolerance for expressive code is higher. As long as the linter is configurable I don’t really care.
loganlinnover 3 years ago
Something tells me the author would appreciate the minutia of working in functional languages that tend to avoid entire classes of problems like those described and the dogma used to fight it.
jbverschoorover 3 years ago
I have more problems with:<p>- extensive small functions&#x2F;methods<p>- people who don’t use early escapes
评论 #28402574 未加载
评论 #28403108 未加载
cafardover 3 years ago
In one of Raymond Hettinger&#x27;s YouTube presentations, he speaks slightingly of pylint. These days I use flake8, but not pylint.
29athrowawayover 3 years ago
&gt; less code is better than more code, and this block can be rewritten more concicely<p>Conciseness is not necessarily better.<p>- Does this idiom make debugging easier? no, it doesn&#x27;t.<p>- Does this idiom make it easy to identify where a branch starts and ends? no, it doesn&#x27;t. Before you could use indentation alone, now you have to read the statement.<p>- Is it slightly faster to type? Maybe. But that does not matter because time spent typing is a tiny tiny fraction of the time you spend as a developer. You spend much more time reading than typing.
reportgunnerover 3 years ago
How is this new ? Perhaps it&#x27;s new for the author. Python one liner ifs were not introduced yesterday.
phendrenad2over 3 years ago
&gt; A while loop introduces unbounded computation<p>Someone needs to inform this guy that generators exist
gigatexalover 3 years ago
i dunno re: the while loop -- a while loop with a condition that breaks the loop is perfectly fine by me.
lxeover 3 years ago
There shouldn&#x27;t be so many ways to do loops. Assembly got it right the first time.
aimorover 3 years ago
I just want to read and write:<p><pre><code> x = if condition(): 4 else: 5</code></pre>
throwaway81523over 3 years ago
<a href="https:&#x2F;&#x2F;xkcd.com&#x2F;1833&#x2F;" rel="nofollow">https:&#x2F;&#x2F;xkcd.com&#x2F;1833&#x2F;</a> has some good ones.
apocolyps6over 3 years ago
Most of the time when I see python ternary in the wild, it makes the code less readable, not more. Why not just define something like this if you want oneliners?<p><pre><code> def if_then_else(cond, true_case, false_case): if cond: return true_case return false_case x = if_then_else(condition, 4, 5)</code></pre>
评论 #28401682 未加载