137 karma · joined August 2, 2012
This is what I'd prefer
from dataclasses import dataclass, field
@dataclass
class MyClass:
x = field()
but it produces an error because fields need to be declared with a type annotation. This is the GvR recommended way to get around it: @dataclass
class MyClass:
x: object
You could use the typing.Any type instead of object, but then you need to import a whole typing library to use untyped dataclasses. I highly prefer the former code block.There's a big thread discussing the issue on python-dev somewhere. Also some discussion in https://github.com/ericvsmith/dataclasses/issues/2#issuecomm...
Anyway, it's not a huge issue—attrs is great and there's no reason not to use it instead for untyped Python.
Similar to how few people would put their first application out in public, I prefer to keep my thesis private unless someone finds the information really useful :)
I tested how Mechanical Turkers (N=~400) chose plans on pricing pages with 4-tiered subscriptions plans, for both a file sharing service and a payroll software service. Each respondent was randomly assigned to one of 4 conditions, where the presented pricing page was slightly different. The scenario was framed as choosing a SaaS plan for a company they're employed at.
The first variable I varied was plan order. Half the respondents saw a pricing page with plans in increasing price order (cheapest first), the other half in decreasing price order (most expensive first). There was a statistically significant difference between the plan choices for these groups; respondents in the most expensive plan first condition chose a more expensive plan. This phenomenon has been seen before outside SaaS, and it's called the price order effect.
Another variable I tested was exchanging the cheapest ($5) plan for a free plan. Half the respondents saw a free plan, the other half a $5 plan. There was no statistically significant difference in the plan choice for these groups.
Getting familiar with previous literature, I would surface a couple of general thoughts:
- The most expensive plan first approach may give the visitor a more expensive image of the product, a higher "reference price". If a prospective customer is comparing two products from two different companies, they may favor the one that seems cheaper (has a lower "reference price") even if the offerings may provide similar value.
- The hypothesized mechanism for the price order effect is that you don't look at all the options as a whole, but you begin by assessing the first option, which is the leftmost one for us reading left-to-right, and then judge the next option by comparing it to the previous one, and so on. You compare added (more features/less cost) and lost (less features/more cost) value. Because we weigh losses heavier than benefits, there's an inertia toward the initial options. Only options with benefits that greatly outweigh losses combat that inertia. Hence respondents tended to choose plans more on the left.
fn(1)(2)(3)
That's a big drawback for me. Libraries like Ramda allow one or more arguments per function call: fn(1, 2, 3) === fn(1, 2)(3) === fn(1)(2, 3)
That's what makes the verbosity unbearable, as each type of call needs its own type.A type system would detect these cases, but TypeScript and Flow don't have great support for curried functions. Typing them is very verbose.
The library has a well-written tutorial that doesn't require previous knowledge about parser combinators.
It's not a silver bullet though. Some property-based tests are easy to write but offer little value. Sometimes you spend more time writing code to generate the correct inputs than the value of the test warrants. It has a learning curve. Still, I think it is the most powerful tool you can master for testing.
They're common patterns a lot of people use without knowing anything about CT, for example if you fold/reduce over a collection with an initial value, and the collection may be empty, you're looking at a monoidal operation. You can call the initial value a constant identity. Like sum, product.
If you fold/reduce over a collection where the collection may not be empty, and you need to use the first element as the initial value, you're looking at a semigroup operation. Like min/max/mean.
def find(predicate, iterable, default=None):
"""Returns the first value that matches predicate, otherwise default=None"""
return next(
(x for x in iterable if predicate(x)),
default
)
Which turns the expression to find(lambda x: 'widgets' in x, mixed_widgets)['widgets']There are some gotchas where you need to explicitly copy (itertools.tee) iterators when you have multiple consumers, and be careful with mutable values, but it's manageable.
It would be nice to use curried functions as functools.partial gets verbose, but at that point you're far from Pythonic code.
I can't remember where I stumbled upon that, but it implements an object database over PostgreSQL and offers a GraphQL superset for querying. Don't know if it's still in active development, but it looks interesting.
I really like that it builds up from the basics, starting from lambda calculus, and is also very complete in explaining every concept. I don't feel like anything is left unexplained. This is important, because coming from dynamically typed imperative languages, a lot of concepts in Haskell are so alien that you feel like you're learning programming all over again.
The exercises set it apart from other resources. They're plentiful, start simple, but quickly increase in difficulty. A lot of times I thought I had a concept mastered until the exercises presented gaps in my knowledge -- which made me learn the concept that much better.
The completeness means it's a long book (currently 1233 pages). You'll probably need a healthy dose of existing motivation to learn Haskell to get through it.
If you decide to use it, you might want to look at the development of the original Django Twoscoops Project (https://github.com/twoscoops/django-twoscoops-project) during the last year or so, as they haven't been pulled in to my repo.
Interface patterns have their best use cases and the designer needs to pick the right one for each part of the design, making sure it works as a whole.
Typography is based on making text easily readable - there's always some leeway for opinionated typography but a designer shouldn't stray far from best practices.
While the exact colors in a palette can be opinionated, they too have characteristics that should be assessed without opinion. Are there enough contrast between the colours? What if the user is colorblind? Will people with low vision be able to see everything clearly, especially text? Are the colors appropriate for their intended use, for example a red hue for alert, green for success)?
"It does not look right" and "it does not work" are the kind of feedback you get from people who don't know the inner logics of a design. Feedback from an experienced designer might not mention aesthetics at all.
If you're going to use effects, make sure they actually contribute to or complement the content.
It's not a scientific number by any means, rather a general "consensus" derived from all the typography literature and articles I've read. The measure is not as simple as it seems, though; Readers seem to prefer a shorter measure while reading speed is actually increased with a longer measure, like shown in this study:
http://psychology.wichita.edu/surl/usabilitynews/72/LineLeng...
Erroneous: Research shows that consumers with a utilitarian motivation find a low-arousal environment more pleasuraigh-arousal one.
Fixed: Research shows that consumers with a utilitarian motivation find a low-arousal environment more pleasurable than a high-arousal one.